#include "simulate.h"
#include <cassert>
#include <new>
#include <malloc.h>
#include <algorithm>
//#include <time.h>
#include <sys/time.h>

extern int trace_size;
int tsw1,tsw2;
float err1;

Simulate::~Simulate(void){
	passiveGates.clear();	
}

void Simulate::initPruning()
{
        for(int i=0; i<Ci->signalSize(); ++i)
                Ci->getSignal(i)->pruned = 0;
}

void Simulate::initMultithread_GREEDY(int thread_num){
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                Ci->getSignal(i)->MulTTraced.clear();
                for(int j = 0; j < thread_num; j++)
                        if(Ci->getSignal(i)->selected == 0)
                                Ci->getSignal(i)->MulTTraced[j] = false;
                        else
                                Ci->getSignal(i)->MulTTraced[j] = true;
        }
        
}

void Simulate::initMultithread_PRUNE(int thread_num){
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                Ci->getSignal(i)->MulTTraced.clear();
                for(int j = 0; j < thread_num; j++)
                        Ci->getSignal(i)->MulTTraced[j] = false;
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i){
                for(int j = 0; j < thread_num; j++)
                        if(Ci->getFlipflop(i)->getOutput(0)->pruned == 0)
                                Ci->getFlipflop(i)->getOutput(0)->MulTTraced[j] = true;
                        else
                                Ci->getFlipflop(i)->getOutput(0)->MulTTraced[j] = false;
        }
        
}

void Simulate::initMultThread(int thread_num){

        sim_round = 0;
        sigList = new SG[thread_num]; 
        CurSig = new Signal*[thread_num];
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                if(Ci->getSignal(i)->untouchible == true)
                {
                        for(int j = 0; j < thread_num; j++)
                        {
                                myDataType f,g;
                                if(Ci->getSignal(i)->valArray[0] == 0)
                                {
                                        f.assign((BIT_TYPE)0);
                                        g = f;
                                        Ci->getSignal(i)->Mult_Val0[j] = f;
                                        Ci->getSignal(i)->Mult_Val1[j] = f;
                                        continue;
                                }
                                
                                f.assign((BIT_TYPE)1);
                                g = f;
                                for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++)
                                {
                                        f = f << 1;
                                        f = f | g;
                                }
                                
                                Ci->getSignal(i)->Mult_Val0[j] = f;
                                Ci->getSignal(i)->Mult_Val1[j] = f;
                        }
                        
                        continue;
                }
                
                for(int j = 0; j < thread_num; j++)
                {
                        myDataType f,g;
                        f.assign((BIT_TYPE)1);
                        g = f;
                        for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++)
                        {
                                f = f << 1;
                                f = f | g;
                        }

                        Ci->getSignal(i)->Mult_Val0[j].assign((BIT_TYPE)0);
                        Ci->getSignal(i)->Mult_Val1[j] = f;
                }
                
                Ci->getSignal(i)->chosen = false;
        }
}


void Simulate::initSimulateHybrid(){
        
	for(int i=0; i<Ci->signalSize(); ++i){
                
                if(Ci->getSignal(i)->getTraced() == false) 
                {
                        Ci->getSignal(i)->setVal(Z);
                        Ci->getSignal(i)->setFlag0(0);
                        Ci->getSignal(i)->setFlag1(0);
                }
                
                Ci->getSignal(i)->stored = 0;//should not be here 
        }
        
        for(int i=0; i<Ci->gateSize(); ++i){
                Ci->getGate(i)->backRestored = false;
                Ci->getGate(i)->forceRestored = false;
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                Ci->getFlipflop(i)->backRestored = false;
                Ci->getFlipflop(i)->forceRestored = false;
        }
}

void Simulate::initSimulate(bool a){
	for(int i=0; i<Ci->signalSize(); ++i){
		Ci->getSignal(i)->setVal(Z);
                Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
	}
	for(int i=0; i<Ci->flipflopSize(); ++i)
		Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
}

void Simulate::initSimulate(void){
	
        const int interval = SIM_CYCLE_NUM;
        for(int i=0; i<Ci->signalSize(); ++i){
                
                Ci->getSignal(i)->preset = false;
                Ci->getSignal(i)->untouchible = false;
		Ci->getSignal(i)->setVal(Z);
		Ci->getSignal(i)->val = Z;
		Ci->getSignal(i)->sw = 0;
		Ci->getSignal(i)->sw1 = 0;
		Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
                Ci->getSignal(i)->pruned = 0;
                Ci->getSignal(i)->selected = 0;
                Ci->getSignal(i)->stored = 0;
                
                Ci->getSignal(i)->valArray = new Value[interval];
                for(int j = 0; j < interval; j++)
                        Ci->getSignal(i)->valArray[j] = Z;
	}
        
	for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                Ci->getFlipflop(i)->getOutput(0)->Cur_P = 0.0;
                Ci->getFlipflop(i)->getOutput(0)->Cur_P0 = 0.0;
                Ci->getFlipflop(i)->getOutput(0)->Cur_P1 = 0.0;
		Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
        }
        /*
        //de-assert the control inputs
        string ctrInput;
        string val;
        while(1)
        {
                cout<<"Input the name for the deasserted signal"<<endl;
                cin >> ctrInput;
                
                if(ctrInput == "end")
                        break;
                
                cout<<"Input the value for the deasserted signal"<<endl;
                cin >> val;
                
                for(int i=0; i<Ci->signalSize(); ++i){
                        if(Ci->getSignal(i)->getName() == ctrInput)
                        {
                                Ci->getSignal(i)->untouchible = true;
                                Value v = (Value)atoi(val.c_str());
                                Ci->getSignal(i)->setVal(v);
                                for(int j = 0; j < interval; j++)
                                        Ci->getSignal(i)->valArray[j] = v;
                        }
                }
        }
        */
}

void Simulate::setResets(void){
	for(int i=0; i<Ci->flipflopSize(); ++i)
		Ci->getFlipflop(i)->getInput(2)->setVal(One);
	
	for(int i=0; i<Ci->signalSize(); ++i)
		if(Ci->getSignal(i)->getName()[0]=='R')
			Ci->getSignal(i)->setVal(One);
	return;
}

void Simulate::setSigValues(vector<Signal *> sigs, vector<Value> vals){
	for(unsigned i=0; i<sigs.size(); ++i)
		sigs[i]->setVal(vals[i]);
}

void Simulate::setTraceValues(vector<Value> vals){
	for(unsigned i=0; i<tracedSigs.size(); ++i)
		tracedSigs[i]->setVal(vals[i]);
}

void Simulate::initGates(void){
	for(int i=0; i<Ci->gateSize(); ++i){
		Ci->getGate(i)->setVisited(false);
		Ci->getGate(i)->setBackwardVisited(false);
		Ci->getGate(i)->passive = false;
	}
	for(int i=0; i<Ci->flipflopSize(); ++i){
		Ci->getFlipflop(i)->setVisited(false);
		Ci->getFlipflop(i)->setBackwardVisited(false);
	}
	return;
}

bool Simulate::PrintSignalBitVal(Signal* sig, int Tid)
{
        const int bit_num = 8 * sizeof(BIT_TYPE);
        const int check_highest_bits = TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE));
        cout<<"For signal "<<sig->getName()<<endl;
        for(int i = 0; i < TRACE_DEPTH_NUM; i++)
        {
                
                for(int j = 0; j < 8 * sizeof(BIT_TYPE); j++)
                {
                        BIT_TYPE temp1 = sig->Mult_Val0[Tid].bits[i];
                        BIT_TYPE temp2 = sig->Mult_Val1[Tid].bits[i];

                        temp1 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                        temp1 >>= bit_num - 1 - j;
                        
                        temp2 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                        temp2 >>= bit_num - 1 - j;
                        
                        if(temp1 == temp2)
                                cout<<temp1;
                        else
                                cout<<"X";
                }
        }
        cout<<endl;
}

bool Simulate::PrintMyDataType(myDataType f)
{
        for(int i = 0; i < TRACE_DEPTH_NUM; i++)
        {
                BIT_TYPE temp = f.bits[i];
                printf("%lx\t", temp);
        }
        cout<<endl;
}

bool Simulate::SimInitDFFValue()
{
        srand ( time(NULL) );
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n, count_traced; long st;
        
        Value vals[]={Zero,One,Z,X};
        for(int j = 0; j < SIM_CYCLE_NUM + 1; j++)
        {
                vector<Signal*> sig;
                vector<Value> val;
                
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        sig.push_back(Ci->getInput(i)->getInput(0));
                }
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                                val.push_back(vals[rand()%2]);
                                for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
                                        if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
                                                Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
                                                passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
                                        }
                                }
                        }
                        else{
                                val.push_back(Zero);
                        }
                }
                
                setSigValues(sig,val);
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getInput(2)->setVal(One);
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        if(Ci->getSignal(i)->getName()[0]=='R')
                                Ci->getSignal(i)->setVal(One);
                
                sim1cycle();
                
                if( j > 0 )
                {
                        for(int i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->getVal() == 1)
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = One;
                                else if(Ci->getFlipflop(i)->getOutput(0)->getVal() == 0)
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = Zero;
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->setOutput();
                
        }
        
        return true;
}

bool Simulate::SimInitDFFValue(string filename)
{
        srand ( time(NULL) );
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n, count_traced; long st;
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        ofstream out(str.c_str());
        
        string str1 = filename;
        str1.erase(str1.begin() + str1.find("bench"), str1.end());
        str1 += "gate_weight";
        ofstream kout(str1.c_str());
        
        cout << "DFF map file name is " << str << endl;

        Value vals[]={Zero,One,Z,X};
        
        for(int i=0; i<Ci->gateSize(); ++i){
                Ci->getGate(i)->weight = 0.0;
        }
        
        for(int j = 0; j < SIM_CYCLE_NUM + 1; j++)
        {
                vector<Signal*> sig;
                vector<Value> val;
                
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        sig.push_back(Ci->getInput(i)->getInput(0));
                }
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                                val.push_back(vals[rand()%2]);
                                for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
                                        if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
                                                Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
                                                passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
                                        }
                                }
                        }
                        else{
                                val.push_back(Zero);
                        }
                }
                
                setSigValues(sig,val);
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getInput(2)->setVal(One);
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        if(Ci->getSignal(i)->getName()[0]=='R')
                                Ci->getSignal(i)->setVal(One);
                
                sim1cycle();
                
                if( j > 0 )
                {
                        //flipflop has weight?
                        for(int i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->getVal() == One){
                                        out << "1" << endl;
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = One;
                                        
                                        if(j > 1 && Ci->getFlipflop(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getFlipflop(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getFlipflop(i)->weight += 1.0;
                                }
                                else if(Ci->getFlipflop(i)->getOutput(0)->getVal() == Zero){
                                        out << "0" << endl;
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = Zero;
                                        
                                        if(j > 1 && Ci->getFlipflop(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getFlipflop(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getFlipflop(i)->weight += 1.0;
                                }
                        }
                        
                        for(int i=0; i<Ci->gateSize(); ++i)
                        {
                                if(Ci->getGate(i)->getOutput(0)->getVal() == Zero){
                                        Ci->getGate(i)->getInput(0)->valArray[j-1] = Zero;
                                        
                                        if(j > 1 && Ci->getGate(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getGate(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getGate(i)->weight += 1.0;
                                }
                                else if(Ci->getGate(i)->getOutput(0)->getVal() == One){
                                        Ci->getGate(i)->getInput(0)->valArray[j-1] = One;
                                        
                                        if(j > 1 && Ci->getGate(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getGate(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getGate(i)->weight += 1.0;
                                }
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->setOutput();
                
        }
        
        for(int i=0; i<Ci->gateSize(); ++i)
                kout << Ci->getGate(i)->weight / (double)(SIM_CYCLE_NUM - 1) << endl;
        
        out.close();
        kout.close();
        return true;
}

bool Simulate::LoadDFFMap(string filename)//accompanied with siminitDFFvalue
{
        const int MAX_LINE_LENGTH  = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        
        ifstream in(str.c_str());
        if (!in.is_open()) {
                cerr << "Can't open init DFF map file" << endl;
                exit(1);
        }
        
        string str1 = filename;
        str1.erase(str1.begin() + str1.find("bench"), str1.end());
        str1 += "gate_weight";
        ifstream kin(str1.c_str());
        if (!kin.is_open()) {
                cerr << "Can't open gate weight file" << endl;
                exit(1);
        }
        
        for(int k=0; k<Ci->gateSize(); ++k)
        {
                kin.getline(line_buffer, MAX_LINE_LENGTH);
                Ci->getGate(k)->weight = atof(line_buffer);
                //cout << " gate " << k << " 's weight is " << Ci->getGate(k)->weight << endl;
        }
        
        int i = 0, j = 0;
        while(in.getline(line_buffer, MAX_LINE_LENGTH)){
                if(!strcmp(line_buffer,"0"))
                        Ci->getFlipflop(i++)->getOutput(0)->valArray[j] = Zero;
                else
                        Ci->getFlipflop(i++)->getOutput(0)->valArray[j] = One;
                
                if(i == Ci->flipflopSize())
                {
                        i = 0;
                        j++;
                }
        }
        
        /*
        ofstream out("check");
        for(i = 0 ; i < Ci->flipflopSize(); i++)
        {
                out << "DFF " << i << endl;
                for(j = 0 ; j < SIM_CYCLE_NUM; j++)
                {
                        //assert(Ci->getFlipflop(i)->getOutput(0)->valArray[j] != 2);
                        out << Ci->getFlipflop(i)->getOutput(0)->valArray[j] << "\t";
                }
                out <<endl;
        }
        
        out.close();
        */
        
        in.close();
        kin.close();
        return true;
}

bool Simulate::LoadInitDFFValue(int offset, int Tid)
{
        myDataType f;
        f.assign((BIT_TYPE)1);

        assert(offset <=  SIM_CYCLE_NUM - TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(Tid) == true)
                {
                        for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                        {
                                assert(Ci->getFlipflop(i)->getOutput(0)->valArray[j + offset] != Z);
                                
                                if(Ci->getFlipflop(i)->getOutput(0)->valArray[j + offset] == 1)
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] 
                                                = ((Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] << 1));
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] =
                                                (Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] | f);
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] 
                                                = ((Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] << 1));
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] =
                                                (Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] | f);
                                }
                                else
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] 
                                                = (Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] << 1);
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] 
                                                = (Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] << 1);
                                }
                                
                        }
                }
        }
        
        return true;
}

double Simulate::MultCalVN(int Tid)
{
        int mark = 0;
        sigList[Tid].SL.clear();
        
        for(int i=0; i<Ci->inputSize(); ++i)
                if(Ci->getInput(i)->getInput(0)->untouchible == true)
                        sigList[Tid].SL.push_back(Ci->getInput(i)->getInput(0));
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(Tid) == true)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == "g2883")
                                mark = 1;
                        
                        sigList[Tid].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        while (!sigList[Tid].SL.empty())
        {
                CurSig[Tid] = sigList[Tid].SL.front();
                sigList[Tid].SL.erase(sigList[Tid].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                //if(mark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); it!=sigList[Tid].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[Tid], 0);
                        cin.get();
                }
#endif
        
                if(CurSig[Tid]->outputSize()!=0){
                        if(CurSig[Tid]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(CurSig[Tid]->inputSize()!=0){
                        if(CurSig[Tid]->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){                                        
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid)==false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }       
        }
        
        pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
        int rc = pthread_mutex_lock(&lock);
        assert(rc == 0);
        BIT_TYPE count = 0;
        for(int i=0; i<Ci->flipflopSize(); ++i)
                count += Ci->getFlipflop(i)->getOutput(0)->isMultKnown(Tid);
        
        //PrintRestoreMap(Tid);
        double temp_VN = (double)count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        pthread_mutex_unlock(&lock);
        return temp_VN;
}

double Simulate::MultCalVNWOLOCK(int Tid)
{
        int mark = 0;
        sigList[Tid].SL.clear();
        
        for(int i=0; i<Ci->inputSize(); ++i)
                if(Ci->getInput(i)->getInput(0)->untouchible == true)
                {
                        sigList[Tid].SL.push_back(Ci->getInput(i)->getInput(0));
                }

        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(Tid) == true)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == "g2883")
                                mark = 1;
                        
                        sigList[Tid].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        while (!sigList[Tid].SL.empty())
        {
                CurSig[Tid] = sigList[Tid].SL.front();
                sigList[Tid].SL.erase(sigList[Tid].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                //if(mark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); it!=sigList[Tid].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[Tid], 0);
                        cin.get();
                }
#endif
        
                if(CurSig[Tid]->outputSize()!=0){
                        if(CurSig[Tid]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(CurSig[Tid]->inputSize()!=0){
                        if(CurSig[Tid]->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){                                        
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid)==false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }       
        }
        
        BIT_TYPE count = 0;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                int temp = Ci->getFlipflop(i)->getOutput(0)->isMultKnown(Tid);
                Ci->getFlipflop(i)->getOutput(0)->Cur_P = (double)temp / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                count += temp;
        }
        
        //PrintRestoreMap(Tid);
        double temp_VN = (double)count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        return temp_VN;
}

pair<double,double> Simulate::reportSRR_GRR(void)
{
        int mark = 0;
        sigList[0].SL.clear();
        
        for(int i=0; i<Ci->inputSize(); ++i)
                if(Ci->getInput(i)->getInput(0)->untouchible == true)
                {
                        sigList[0].SL.push_back(Ci->getInput(i)->getInput(0));
                }

        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(0) == true)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == "g2883")
                                mark = 1;
                        
                        sigList[0].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        while (!sigList[0].SL.empty())
        {
                CurSig[0] = sigList[0].SL.front();
                sigList[0].SL.erase(sigList[0].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                //if(mark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); it!=sigList[0].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[0], 0);
                        cin.get();
                }
#endif
        
                if(CurSig[0]->outputSize()!=0){
                        if(CurSig[0]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(CurSig[0]->inputSize()!=0){
                        if(CurSig[0]->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<CurSig[0]->inputSize(); ++i){
                                        
                                        if(CurSig[0]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getInput(i)->setBitInput(0) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getInput(i)->isBitBackwardActive(0)){                                        
                                                for(int j=0; j<CurSig[0]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < CurSig[0]->inputSize(); ++i){
                                        
                                        if(CurSig[0]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getInput(i)->setBitInput(0)==false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getInput(i)->isBitBackwardActive(0)){
                                                for(int j=0; j<CurSig[0]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }       
        }
        
        BIT_TYPE count = 0;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                int temp = Ci->getFlipflop(i)->getOutput(0)->isMultKnown(0);
                Ci->getFlipflop(i)->getOutput(0)->Cur_P = (double)temp / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                count += temp;
        }
        
        //PrintRestoreMap(Tid);
        double SRR = (double)count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        
        double w_count = 0.0;
        double tot_weight = 0.0;
        for(int i=0; i<Ci->gateSize(); ++i)
        {
                int temp = Ci->getGate(i)->getOutput(0)->isMultKnown(0);
                w_count += Ci->getGate(i)->weight * temp;
                tot_weight += Ci->getGate(i)->weight;
        }
        
        cout << "total weight is " << tot_weight << endl;
        //PrintRestoreMap(Tid);
        double GRR = w_count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE))) / tot_weight;//davoodi's idea 
        return make_pair(SRR, GRR);
}

void Simulate::PrintRestoreMap(int Tid){
}

bool lessRStime(Signal* a, Signal* b)
{
        return (a->RStime < b->RStime);
}

bool moreRStime(Signal* a, Signal* b)
{
        return (a->RStime < b->RStime);
}

double Simulate::MultComputVN(int offset){
	
        SimInitDFFValue();
        initMultThread(1);
        LoadInitDFFValue(offset,0);
        return MultCalVNWOLOCK(0);
}

void* work(void *args)
{
        myWorkarg* mwa = new myWorkarg;
        mwa = (myWorkarg*) args;
        
        myRetarg* mra = new myRetarg;
        mra->Tid = mwa->Tid;
        mra->VN = mwa->Sim->MultCalVN(mra->Tid);
        return (void*) mra;
}

pair<double, double> Simulate::simSelect(const int trace_size, const char* filename){
        
        Conf* c1;
        Confset* C1;
        clearTraced();
        
        vector<Signal*>::iterator it;
        struct timeval start1, finish1, finish2, finish3;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_greedy";
        
        int i, j = 0;
        
	stringstream ss;
	cout<<"file name is "<<tmp<<endl;        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        
        const int thread_max = 24;

        initSimulate();
        //SimInitDFFValue();
        LoadDFFMap(filename);
        gettimeofday(&start1, NULL);
        
        while(1)
        {
                
                int pos = 0;
                C1 = new Confset();
                
                while(pos < Ci->flipflopSize())
                {
                        int thread_num = (Ci->flipflopSize()-pos >= thread_max)? thread_max : Ci->flipflopSize()-pos;
                        pthread_t PTs[thread_num];
                        
                        initMultithread_GREEDY(thread_num);
                        
                        j = 0;
                        for(i = pos; i < pos + thread_num; ++i)
                        {
                                
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(true, j);
                                c1 = new Conf();
                                c1->tracedSigs.push_back(Ci->getFlipflop(i)->getOutput(0));
                                C1->confs.push_back(c1);
                                
                                j++;
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 3)
                        {       
                                
                                initMultThread(thread_num);
                                
                                j = 0;
                                for(i = pos; i < pos + thread_num; ++i)
                                {
                                        myWorkarg* mwa= new myWorkarg;
                                        mwa->Tid = j;//should add pos later
                                        mwa->Sim = this;
                                        LoadInitDFFValue(17 + seed_num * 200,j);
                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                        
                                        j++;
                                }
                        
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                
                                        C1->confs[mra->Tid + pos]->TV += mra->VN;
                                        C1->confs[mra->Tid + pos]->TVNC += mra->VN;
                                
                                        delete mra;
                                }
                                
                                seed_num++;
                        }
                        
                        pos = i;
                }
                
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                C1->confs[0]->tracedSigs[0]->selected = 1;
                tracedSigs.push_back(C1->confs[0]->tracedSigs[0]);
                
                cout << "selected signal in this round is " << C1->confs[0]->tracedSigs[0]->getName() << endl;
                
                int flag = 0;
                for(i=0; i<Ci->flipflopSize(); ++i)
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == C1->confs[0]->tracedSigs[0]->getName()){
                                cout << "flipflop number is " << i << endl;
                                flag = 1;
                                break;
                        }
                
                assert(flag == 1);

                if(tracedSigs.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 3 <<endl;
                        
                        double tmp_SRR = 0.0;
                        double tmp_GRR = 0.0;
                        std::pair<double, double> SRR_GRR;

                        i = 0;
                        while ( i < 3){
                
                                //cout << "Selected signal size is " << tracedSigs.size() << endl;
                
                                for(int j=0; j<Ci->flipflopSize(); ++j)
                                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                                //cout<< "seleted signals' outputs names are...." << endl;
                                for(it = tracedSigs.begin(); it != tracedSigs.end(); it++){
                                        //cout<<(*it)->getName()<<endl;
                                        //report<<(*it)->getName()<<endl;
                                        (*it)->setTraced(true,0);
                                        //tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));// why we need this line?
                                }
                
                                initMultThread(1);
                                LoadInitDFFValue(100 + i * 250, 0);
                                SRR_GRR = reportSRR_GRR();
                                tmp_SRR += SRR_GRR.first;
                                tmp_GRR += SRR_GRR.second;
                
                                i++;
                        }
        
                        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
                        cout << "SRR is " << tmp_SRR / 3.0<< "\t"; 
                        cout << "GRR is " << tmp_GRR / 3.0 << endl; 
        
                }
                
                if(tracedSigs.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;

                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 3<<endl;
                        
                        double tmp_SRR = 0.0;
                        double tmp_GRR = 0.0;
                        std::pair<double, double> SRR_GRR;

                        i = 0;
                        while ( i < 3){
                
                                cout << "Selected signal size is " << tracedSigs.size() << endl;
                
                                for(int j=0; j<Ci->flipflopSize(); ++j)
                                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                                cout<< "seleted signals' outputs names are...." << endl;
                                for(it = tracedSigs.begin(); it != tracedSigs.end(); it++){
                                        cout<<(*it)->getName()<<endl;
                                        report<<(*it)->getName()<<endl;
                                        (*it)->setTraced(true,0);
                                        //tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));// why we need this line?
                                }
                
                                initMultThread(1);
                                LoadInitDFFValue(100 + i * 250, 0);
                                SRR_GRR = reportSRR_GRR();
                                tmp_SRR += SRR_GRR.first;
                                tmp_GRR += SRR_GRR.second;
                
                                i++;
                        }
        
                        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
                        cout << "SRR is " << tmp_SRR / 3.0<< "\t"; 
                        cout << "GRR is " << tmp_GRR / 3.0 << endl; 
        
                }
                
                cout<< "Trace size is in this round is " << tracedSigs.size() << endl;
                cout<< "Total Visibility is " << C1->confs[0]->TV / 3<< endl;
                
                if(tracedSigs.size() == trace_size)
                        break;
                
                C1->~Confset();
                
        }
        
        gettimeofday(&finish3, NULL);
        cout<< "total runtime for Simulation-Based trace selection when selecting "<< trace_size <<" is: "
            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< "total runtime for Simulation-Based trace selection when selecting "<< trace_size <<" is: "
              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< tracedSigs.size() << endl;
        report<< "seleted signals are...." << endl;
        
        cout<< "seleted signals are...." << endl;
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                report<<(*it)->getName()<<"\t";
                cout<<(*it)->getName()<<"\t";
        }
        cout<<endl;

        report<<endl;        
        report<<"Final Visibility is "<< C1->confs[0]->TV / 3<<endl;
        
        double tmp_SRR = 0.0;
        double tmp_GRR = 0.0;
        std::pair<double, double> SRR_GRR;

        i = 0;
        while ( i < 3){
                
                cout << "Selected signal size is " << tracedSigs.size() << endl;
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                cout<< "seleted signals' outputs names are...." << endl;
                for(it = tracedSigs.begin(); it != tracedSigs.end(); it++){
                        cout<<(*it)->getName()<<endl;
                        report<<(*it)->getName()<<endl;
                        (*it)->setTraced(true,0);
                        //tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));// why we need this line?
                }
                
                initMultThread(1);
                LoadInitDFFValue(100 + i * 250, 0);
                SRR_GRR = reportSRR_GRR();
                tmp_SRR += SRR_GRR.first;
                tmp_GRR += SRR_GRR.second;
                
                i++;
        }
        
        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
        cout << "SRR is " << tmp_SRR / 3.0<< "\t"; 
        cout << "GRR is " << tmp_GRR / 3.0 << endl; 
        
        //return MultCalVNWOLOCK(0);
        
        /*
        int thread_num = (Ci->flipflopSize()-pos >= thread_max)? thread_max : Ci->flipflopSize()-pos;
        pthread_t PTs[thread_num];
                
        initMultithread_GREEDY(thread_num);
                
        j = 0;
        for(i = 0; i < 3; ++i)
        {
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,i);
                
                for(j = 0; j < tracedSigs.size(); j++)
                        tracedSigs[j]->setTraced(true, i);

                c1 = new Conf();
                for(j = 0; j < tracedSigs.size(); j++)
                        c1->tracedSigs.push_back(tracedSigs[j]);
                
                C1->confs.push_back(c1);
                        
                j++;
        }
        
        int seed_num = 0;
        while(seed_num < 3)
        {
                initMultThread(3);                
                
                j = 0;
                for(i = 0; i < 3; ++i)
                {
                        myWorkarg* mwa= new myWorkarg;
                        mwa->Tid = j;//should add pos later
                        mwa->Sim = this;
                        LoadInitDFFValue(17 + seed_num * 200,j);
                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        
                        j++;
                }
                
                for(j = 0; j < 3; j++)
                {
                        myRetarg* mra = new myRetarg;
                        pthread_join(PTs[j], (void**) &mra);
                        
                        C1->confs[mra->Tid + pos]->TV += mra->VN;
                        C1->confs[mra->Tid + pos]->TVNC += mra->VN;
                        
                        delete mra;
                }
                
                seed_num++;
                }
        */
        return make_pair(tmp_SRR / 3.0, tmp_GRR / 3.0);
}


struct moreTraceTV : public binary_function<Signal*, Signal *, bool> {
        bool operator()(const Signal *a, const Signal *b){
                return (a->DFF_visibility > b->DFF_visibility);
        }
};


double Simulate::simSelectValeria(const int trace_size, const char* filename){
        
        Conf* c1;
        int i, j;
        Confset* C1;
        clearTraced();
        vector<Signal*>::iterator it;
        //let the whole procedure of trace size 8, 16, 32 finish in one shot
        //assert(trace_size == 8);
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_prune";
        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        
        const int prune_step = 50;
        const double prune_threshold = 0.93;
        const int thread_max = 24;
        
        initSimulate();
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                addTraced(Ci->getFlipflop(i)->getOutput(0));
        
        //SimInitDFFValue();
        LoadDFFMap(filename);
        
        struct timeval start1, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);

        while(1)
        {
                
                int pos = 0;
                C1 = new Confset();
                
                while(pos < tracedSigs.size())
                {
                        int thread_num = (tracedSigs.size()-pos >= thread_max)? thread_max : tracedSigs.size()-pos;
                        pthread_t PTs[thread_num];
                        
                        initMultithread_PRUNE(thread_num);
                        
                        j = 0;
                        for(i = pos; i < pos + thread_num; ++i)
                        {
                                tracedSigs[i]->setTraced(false, j);
                                
                                c1 = new Conf();
                                c1->tracedSigs.push_back(tracedSigs[i]);
                                C1->confs.push_back(c1);
                                
                                j++;
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 2)
                        {        
                                
                                initMultThread(thread_num);
                                
                                j = 0;
                                for(i = pos; i < pos + thread_num; ++i)
                                {
                                        
                                        myWorkarg* mwa= new myWorkarg;
                                        mwa->Tid = j;//should add pos later
                                        mwa->Sim = this;
                                        LoadInitDFFValue(10 + seed_num * 10,j);
                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                        
                                        j++;
                                }
                                
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                        
                                        C1->confs[mra->Tid + pos]->TV += mra->VN;
                                        tracedSigs[mra->Tid + pos]->DFF_visibility += mra->VN;
                                        
                                        C1->confs[mra->Tid + pos]->TVNC += mra->VN;
                                        delete mra;
                                }
                                
                                seed_num++;
                        }
                        
                        pos = i;
                }
                
                //cout<<"AfterWards________________________________________________________"<<endl;
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                
                if(C1->confs[0]->TV > prune_threshold * Ci->flipflopSize() 
                   && tracedSigs.size() > prune_step + 32)
                {
                        sort(tracedSigs.begin(), tracedSigs.end(), moreTraceTV());
                        
                        for(int i = 0; i < prune_step; ++i)
                                tracedSigs[i]->pruned = 1;
                        
                        tracedSigs.erase(tracedSigs.begin(), tracedSigs.begin() + prune_step);
                        continue;
                }
                
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                it = find(tracedSigs.begin(), tracedSigs.end(), C1->confs[0]->tracedSigs[0]);
                assert( it != tracedSigs.end() );
                
                (*it)->pruned = 1;
                tracedSigs.erase(it);

                if(tracedSigs.size() == 32)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 2<<endl;
                }
                
                if(tracedSigs.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 2<<endl;
                }
                
                cout<< "Trace size is in this round is " << tracedSigs.size() << endl;
                cout<< "Total Visibility is " << C1->confs[0]->TV / 2 << endl;
                
                if(tracedSigs.size() == trace_size)
                        break;
                
                C1->~Confset();
                
        }
        
        gettimeofday(&finish3, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection when selecting 8 is: "
            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< "total runtime for Simulation-Based trace selection when selecting 8 is: "
              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< tracedSigs.size() << endl;
        report<< "seleted signals are...." << endl;
        
        cout<< "seleted signals are...." << endl;
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                report<<(*it)->getName()<<"\t";
                cout<<(*it)->getName()<<"\t";
        }
      
        cout<<endl;
        report<<endl;
        
        printTraced();
        report<<"Final Visibility is "<< C1->confs[0]->TV / 2 <<endl;
        
        return C1->confs[0]->TV / 2;
}


bool Simulate::sim1cycle(void){
	list<Signal*> sigList;
	bool cont=false;
	for(int i=0; i<Ci->flipflopSize(); ++i)
		if(Ci->getFlipflop(i)->getOutput(0)->isKnown())
			sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
        
        int count = 0;
	for(int i=0; i<Ci->inputSize(); ++i)
        {
		if(Ci->getInput(i)->getInput(0)->isKnown())
                {
                        count++;
			sigList.push_back(Ci->getInput(i)->getInput(0));
                }
        }
        
        assert(count == Ci->inputSize());
        
	Signal *s;
        while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                
#ifdef DEBUG_SIMULATE
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
#endif                

                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        //cout << s->getOutput(i)->signature() << endl;
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
				}
			}
			else{
				for(int i=1; i<s->outputSize(); ++i){
                                        
                                        //cout << s->getOutput(i)->signature() << endl;
                                        if(s->getOutput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
				}
			}
		}
	}
        return cont;
}				
	
bool Simulate::sim1cycleBackward(void){
	list<Signal*> sigList;
	bool cont=false;
	for(int i=0; i<Ci->flipflopSize(); ++i)
		if(Ci->getFlipflop(i)->getInput(1)->isKnown())
			sigList.push_back(Ci->getFlipflop(i)->getInput(1));
	Signal *s;
        while (!sigList.empty())
        {
                s = sigList.back();
                sigList.pop_back();
                
                if(s->untouchible == true)
                        continue;

                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
					if(s->getInput(i)->isBackwardActive()){
						s->getInput(i)->setBackwardVisited(true);
						cont=true;
						
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
					}
				}
			}
			else
				for(int i=1; i<s->inputSize(); ++i){
					
                                        if(s->getInput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
					if(s->getInput(i)->isBackwardActive()){
						s->getInput(i)->setBackwardVisited(true);
						cont=true;
						
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
					}
				}
                }
	}
        
        return cont;
}				
	
void Simulate::dump(void){
        for(int i=0; i<Ci->signalSize(); ++i)
                cout<<Ci->getSignal(i)->getName()<<" : "<<Ci->getSignal(i)->getVal()<<','<<Ci->getSignal(i)->getP0()<<','<<Ci->getSignal(i)->getP1()<<endl;
}

void Simulate::dumpOutput(void){
        for(int i=0; i<Ci->outputSize(); ++i)
                cout<<Ci->getOutput(i)->getOutput(0)->getName()<<" : "<<Ci->getOutput(i)->getOutput(0)->getVal()<<endl;
}

void Simulate::simNcycle(int n){
	sim1cycle();
	cin.get();
	for(int i=1; i<n; ++i){
		for(int j=0; j<Ci->flipflopSize(); ++j){
			
			Ci->getFlipflop(j)->setOutput();

		}
		sim1cycle();
	}
}

bool Simulate::sim_event_cycle1(void){
	
        bool test = true;
        bool test2 = false;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){				
                        if(passive[i]->isActive()){
                                test2 = true;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
        return test2;
}

bool Simulate::sim_event_back_cycle1(void){
	
        bool test = true;
        bool test2 = false;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){				
                        if(passive[i]->isBackwardActive()){
                                test2 = true;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
        return test2;
}

void Simulate::sim_event_cycle(void){
	
        bool test = true;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){
                        if(passive[i]->isActive()){
                                for(int k=0; k<passive[i]->outputSize(); ++k)
                                        for(int k1=0; k1<passive[i]->getOutput(k)->outputSize(); ++k1)
						if(!(passive[i]->getOutput(k)->getOutput(k1)->passive)){
							passive[i]->getOutput(k)->getOutput(k1)->passive = true;
							passive.push_back(passive[i]->getOutput(k)->getOutput(k1));
						}
                                passive[i]->passive = false;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
}

void Simulate::sim_event(bool fwBw){
	
	passive.clear();
	for(int i=0; i<Ci->gateSize(); ++i)
        {
                if(Ci->getGate(i)->signature() == INPUT)
                        if(Ci->getGate(i)->getInput(0)->untouchible == true)
                                continue;
                
                passive.push_back(Ci->getGate(i));
        }
	bool test = true;
	while(test){
		if(fwBw){
			test = sim_event_cycle1();
			for(int i=0; i<Ci->flipflopSize(); ++i){
				Ci->getFlipflop(i)->setOutput();
			}
		}
		else{
			test = sim_event_back_cycle1();
			for(int i=0; i<Ci->flipflopSize(); ++i){
				Ci->getFlipflop(i)->setInput();
			}
		}
	}
}


bool Simulate::simAllCycle(){

	bool test = false;
	sim1cycle();
	for(int j=0; j<Ci->flipflopSize(); ++j){
		Ci->getFlipflop(j)->setOutput();
	}
	sim1cycle();sim_event(true);
	return test;
}

void Simulate::simNcycleBackward(int n){
	sim1cycleBackward();
	cin.get();
	for(int i=1; i<n; ++i){
		for(int j=0; j<Ci->flipflopSize(); ++j){
			
			Ci->getFlipflop(j)->setInput();
                        
		}
		sim1cycleBackward();
		cin.get();
	}
}

bool Simulate::simAllCycleBackward(){
	for(int j=0; j<Ci->flipflopSize(); ++j){			
                Ci->getFlipflop(j)->setInput();
        }		
	sim1cycleBackward();
	return true;
}

void Simulate::simProb(int n){
        
        int count= 0;
        vector<Value> val;
        vector<Signal*> sig;
        list<Signal*> sigList;
        Value vals[]={Zero,One,Z,X};

        forwardSimReg(1);
        for(int i=0; i<Ci->signalSize(); ++i)
                Ci->getSignal(i)->pre_val = Ci->getSignal(i)->getVal();
        
        //this is because we set output after forwardSimReg(1) 
        for(int j=0; j<Ci->flipflopSize(); ++j){			
                if(Ci->getFlipflop(j)->getOutput(0)->getVal() != 0)//initially 0
                        sigList.push_back(Ci->getFlipflop(j)->getOutput(0));
        }
        
        for(int cnt = 0; cnt < n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;

                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b')
                        {
                                Value temp_val = vals[rand()%2];
                                if(temp_val != Ci->getInput(i)->getInput(0)->pre_val)
                                {
                                        Ci->getInput(i)->getInput(0)->setVal(temp_val);
                                        Ci->getInput(i)->getInput(0)->pre_val = temp_val;
                                        sigList.push_back(Ci->getInput(i)->getInput(0));
                                }               
                        }
                        else
                                val.push_back(Zero);      
                        
                }
                
                //better check untouchible signal values here
                Signal *s;
                bool cont=false;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be accessed at most twice, should be the case                                                                                                                
                        
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        
                        cout<<"Current signal values "<<endl;
                        for(int i=0; i<Ci->signalSize(); ++i)
                                cout<<Ci->getSignal(i)->getName()<<" has value "<<Ci->getSignal(i)->getVal()<<endl;

                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();

#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature() != INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                //should skip then at the
                                                //end of the cycle set flipflop values
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if( (!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                    && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                                else{
                                        
                                        for(int i=1; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if((!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                   && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
                
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        Ci->getFlipflop(i)->setOutput();
                        if(Ci->getFlipflop(i)->getOutput(0)->getVal() != Ci->getFlipflop(i)->getOutput(0)->pre_val)
                        {
                                Ci->getFlipflop(i)->getOutput(0)->pre_val = Ci->getFlipflop(i)->getOutput(0)->getVal();
                                sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                
        }
        
        //cout<<"Number of Unknow signals after simulation is
        //"<<count/MC_NUM<<endl;
        cout<<"Number of Unknow signals after simulation is "<<count/n<<endl;
        
        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
        
}

void Simulate::simProb(int n, string filename){
        
        int count= 0;
        vector<Value> val;
        vector<Signal*> sig;
        list<Signal*> sigList;
        Value vals[]={Zero,One,Z,X};
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        ofstream out(str.c_str());
        cout << "DFF map name is " << str << endl;
        
        forwardSimReg(1);
        for(int i=0; i<Ci->signalSize(); ++i)
                Ci->getSignal(i)->pre_val = Ci->getSignal(i)->getVal();
        
        //this is because we set output after forwardSimReg(1) 
        for(int j=0; j<Ci->flipflopSize(); ++j){			
                if(Ci->getFlipflop(j)->getOutput(0)->getVal() != 0)//initially 0
                        sigList.push_back(Ci->getFlipflop(j)->getOutput(0));
        }
        
        for(int cnt = 0; cnt < n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;

                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b')
                        {
                                Value temp_val = vals[rand()%2];
                                if(temp_val != Ci->getInput(i)->getInput(0)->pre_val)
                                {
                                        Ci->getInput(i)->getInput(0)->setVal(temp_val);
                                        Ci->getInput(i)->getInput(0)->pre_val = temp_val;
                                        sigList.push_back(Ci->getInput(i)->getInput(0));
                                }               
                        }
                        else
                                val.push_back(Zero);      
                        
                }
                
                //better check untouchible signal values here
                Signal *s;
                bool cont=false;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be accessed at most twice, should be the case                                                                                                                
                        
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        
                        cout<<"Current signal values "<<endl;
                        for(int i=0; i<Ci->signalSize(); ++i)
                                cout<<Ci->getSignal(i)->getName()<<" has value "<<Ci->getSignal(i)->getVal()<<endl;

                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();

#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature() != INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                //should skip then at the
                                                //end of the cycle set flipflop values
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if( (!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                    && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                                else{
                                        
                                        for(int i=1; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if((!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                   && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
                
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        Ci->getFlipflop(i)->setOutput();
                        //this may happen at the beginning of the simulation
                        //assert(Ci->getFlipflop(i)->getOutput(0)->getVal()
                        //!= 2);
                        if(cnt < SIM_CYCLE_NUM)
                                out << Ci->getFlipflop(i)->getOutput(0)->getVal() << endl;
                        
                        if(Ci->getFlipflop(i)->getOutput(0)->getVal() != Ci->getFlipflop(i)->getOutput(0)->pre_val)
                        {
                                Ci->getFlipflop(i)->getOutput(0)->pre_val = Ci->getFlipflop(i)->getOutput(0)->getVal();
                                sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                
        }
        
        //cout<<"Number of Unknow signals after simulation is "<<count/MC_NUM<<endl;
        cout<<"Number of Unknow signals after simulation is "<<count/n<<endl;

        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
        
        out.close();
}


extern vector<int> sim_vals;
void Simulate::forwardSim_event(int n){
	
        Value vals[]={Zero,One,Z,X};
        list<Signal*> sigList;
	vector<Signal*> sig;
	vector<Value> val;
        int count= 0;
        
	for(int i=0; i<Ci->inputSize(); ++i){
		sig.push_back(Ci->getInput(i)->getInput(0));
	}
        
        for(int j=0; j<Ci->flipflopSize(); ++j){
                if(Ci->getFlipflop(j)->getOutput(0)->isKnown() == false)
                        Ci->getFlipflop(j)->getOutput(0)->setVal(Zero);
        }
        
        for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->stored = 0;
                Ci->getSignal(i)->setFlag0(0);
                Ci->getSignal(i)->setFlag1(0);
        }
        
        //before go into the loop, let's first deal with the situation when
        //after simulate 1 cycle, there are still unknow signals
        for(int cnt=0; cnt < n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
		val.clear();
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
				val.push_back(vals[rand()%2]);
				for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
					if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
						Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
						passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
					}
				}
			}
			else{
				val.push_back(Zero);
			}
		}
                
		setSigValues(sig,val);
                bool cont=false;
                
                for(int i=0; i<Ci->inputSize(); ++i)
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                Ci->getInput(i)->getInput(0)->setVal(One);
                
                //this part is for input
                for(int i = 0; i < sig.size(); i++)
                {
                        if( sim_vals[sig[i]->getIndex()] != val[i] && sig[i]->getName()[0] != 'b' && sig[i]->getName()[0] != 'n')
                        {
                                sim_vals[sig[i]->getIndex()] = val[i];
                                sigList.push_back(sig[i]);
                        }
                }
                
                Signal *s;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be
                        //accessed at most twice, should be the case
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature()!=INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                       
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if(s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                        }
                                                }
                                        }
                                }
                                else{
                                
                                        for(int i=1; i<s->outputSize(); ++i){
						
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                       
                                                if(s->getOutput(i)->isActive()){
                                                
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if(s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                        }
                                                }
                                        }
                                }
                        }
                }
                
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
        
                //collecting information for hybrid gates
                int k,bit;
                for(int i = 0; i < Ci->hgateSize(); ++i){
                
                        //collecting backtracing events
                        for(int j = 0; j < Ci->getHGate(i)->inputSize(); j++)
                        {
                                bit = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if(k == j)
                                                continue;
                                        else
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+0][bit] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+0][bit] != 2)
                                                        break;
                                                else
                                                        bit++;
                                }                        
                
                                if(k == Ci->getHGate(i)->inputSize())
                                {
                                        for(k = 0; k < Ci->getHGate(i)->outputSize(); k++)
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+0][Ci->getHGate(i)->inputSize()-1+k] 
                                                   != Ci->getSignal(Ci->getHGate(i)->getOutput(k)->getIndex())->getVal() && 
                                                   ((HybridNode*)Ci->getHGate(i))->events[2*j+0][Ci->getHGate(i)->inputSize()-1+k] != 2)
                                                        break;
                                }
                                else
                                        continue;
                        
                                if(k == Ci->getHGate(i)->outputSize())
                                {
                                        ((HybridNode*)Ci->getHGate(i))->BR_event[2*j+0]++;
                                        continue;
                                }
                        }
                
                        for(int j = 0; j < Ci->getHGate(i)->inputSize(); j++)
                        {
                                bit = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if(k == j)
                                                continue;
                                        else
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+1][bit] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+1][bit] != 2)
                                                        break;
                                                else
                                                        bit++;
                                }
                        
                                if(k == Ci->getHGate(i)->inputSize())
                                {
                                        for(k = 0; k < Ci->getHGate(i)->outputSize(); k++)
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+1][Ci->getHGate(i)->inputSize()-1+k] 
                                                   != Ci->getSignal(Ci->getHGate(i)->getOutput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+1][Ci->getHGate(i)->inputSize()-1+k] != 2)
                                                        break;
                                }
                                else
                                        continue;
                        
                                if(k == Ci->getHGate(i)->outputSize())
                                {
                                        ((HybridNode*)Ci->getHGate(i))->BR_event[2*j+1]++;
                                        continue;
                                }
                        }

                        //collecting forward resotre information
                        int cnt,flag;
                        vector<int*>::iterator it;
                        for(int j = 0; j < Ci->getHGate(i)->outputSize(); j++)
                        {
                                flag = 0;
                                cnt = 0;
                                for(it = ((HybridNode*)Ci->getHGate(i))->OFR0.begin(); it != ((HybridNode*)Ci->getHGate(i))->OFR0.end(); it++)
                                {
                                        for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                                if((*it)[k] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k] != 2)
                                                        break;
                                
                                        if(k == Ci->getHGate(i)->inputSize())
                                        {
                                                flag = 1;
                                                break;
                                        }
                                        cnt++;
                                }
                        
                                if(flag == 1)
                                {
                                        ((HybridNode*)Ci->getHGate(i))->FR0_event[cnt]++;
                                        continue;
                                }
                        
                                flag = 0;
                                cnt = 0;
                                for(it = ((HybridNode*)Ci->getHGate(i))->OFR1.begin(); it != ((HybridNode*)Ci->getHGate(i))->OFR1.end(); it++)
                                {
                                        for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                                if((*it)[k] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k] != 2)
                                                        break;
                                
                                        if(k == Ci->getHGate(i)->inputSize())
                                        {
                                                flag = 1;
                                                break;
                                        }
                                        cnt++;
                                }
                        
                                if(flag == 1)
                                {
                                        ((HybridNode*)Ci->getHGate(i))->FR1_event[cnt]++;
                                        continue;
                                }
                        }
                        
                        cnt = 0;
                        //collecting extra events
                        for(it = ((HybridNode*)Ci->getHGate(i))->extra_events.begin(); it != ((HybridNode*)Ci->getHGate(i))->extra_events.end(); it++)
                        {
                                flag = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if((*it)[0] == k)
                                                continue;
                                        else
                                        {
                                                if((*it)[k+2] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k+2] != 2)
                                                        break;
                                        }
                                }
                        
                                if(k != Ci->getHGate(i)->inputSize())
                                        continue;
                        
                                for(k = Ci->getHGate(i)->inputSize()-1; k < Ci->getHGate(i)->inputSize()-1+Ci->getHGate(i)->outputSize(); k++)
                                {
                                        if((*it)[k+2] != Ci->getSignal(Ci->getHGate(i)->getOutput(k-Ci->getHGate(i)->inputSize()+1)->getIndex())->getVal() 
                                           && (*it)[k+2] != 2)
                                                break;
                                }
                        
                                if(k != Ci->getHGate(i)->inputSize()-1+Ci->getHGate(i)->outputSize())
                                        continue;
                                else
                                        ((HybridNode*)Ci->getHGate(i))->Extra_br_event[cnt]++;
                                
                                cnt++;
                        }
                 }
                
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        Ci->getFlipflop(i)->setOutput();
                }
        }
        
        //cout<<"Number of Unknow signals after simulation is "<<count/MC_NUM<<endl;
        cout<<"Number of Unknow signals after simulation is "<<count/n<<endl;

        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
        Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
}

extern double criteria;
void Simulate::forwardSimReg(int n){
	Value vals[]={Zero,One,Z,X};
	initSimulate();
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
                
                if(Ci->getGate(gi)->getName() == "NAND2") 
                        ((Nand2Node*)Ci->getGate(gi))->initEventStat();
                if(Ci->getGate(gi)->getName() == "NOR2")
                        ((Nor2Node*)Ci->getGate(gi))->initEventStat();
                
                Ci->getGate(gi)->correlated = 0;
                Ci->getGate(gi)->initCorStat();
        }
        
	vector<Signal*> sig;
	vector<Value> val;

	for(int i=0; i<Ci->inputSize(); ++i){
		if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b' && Ci->getInput(i)->getInput(0)->untouchible == false){
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(vals[rand()%2]);
		}
		else{
                        if(Ci->getInput(i)->getInput(0)->untouchible == false)
                        {
                                sig.push_back(Ci->getInput(i)->getInput(0));
                                val.push_back(One);
                        }
		}
	}	
        
	setSigValues(sig,val);
	sim1cycle();
        
	for(int i=0; i<Ci->flipflopSize(); ++i){
                Ci->getFlipflop(i)->setOutput();
        }
	
	for(int cnt=0; cnt<(n-1); ++cnt){
		sig.clear();
		val.clear();
                //if for this part we check the signals that have values
                //different from the previous cycle, we can use an
                //event-driven simulator for much faster simulation of
                //signal probabilities. 
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b' && Ci->getInput(i)->getInput(0)->untouchible == false){
				sig.push_back(Ci->getInput(i)->getInput(0));
				val.push_back(vals[rand()%2]);
			}
			else{
				sig.push_back(Ci->getInput(i)->getInput(0));
				val.push_back(Zero);
			}
		}
                
		setSigValues(sig,val);
		simAllCycle();	

		for(int si=0; si<Ci->signalSize(); ++si){
                        if(Ci->getSignal(si)->getVal()==Zero)
				Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
			if(Ci->getSignal(si)->getVal()==One)
				Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
		}
                
                int j,entry,ret_val;
                //go through all gates, no three-input gates
                for(int gi=0; gi<Ci->gateSize(); ++gi){
                        if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                        {
                                entry=0;
                                for(j = 0; j < 2; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NAND2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == One 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_fr0_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[1]++;
                                        else
                                        {
                                                
                                        }
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NOR2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == Zero 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_fr1_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[1]++;
                                        else
                                        {
                                                
                                        }
                                }

                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else if(Ci->getGate(gi)->inputSize() == 3)//three inputs
                        {
                                entry=0;
                                for(j = 0; j < 3; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else
                        {
                                //do nothing
                        }
                }
	}//n cycles after
        
        int c1=0,c2=0,c3=0;
        int cnt_two_in=0,cnt_three_in=0;
        int impossible=0;
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
#ifdef DEBUG_SIMULATE
                if(Ci->getGate(gi)->getName() == "NAND2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_fr0_c<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[0]<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[1]<<endl;
                }

                if(Ci->getGate(gi)->getName() == "NOR2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_fr1_c<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[0]<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[1]<<endl;
                }
#endif
                if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                {
                        c2++;                          
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria)
                        {
                                cnt_two_in++;
                                Ci->getGate(gi)->correlated++;
                                if(Ci->getGate(gi)->getInput(0)->inputSize() > 1 
                                   || Ci->getGate(gi)->getInput(1)->inputSize() > 1)
                                        impossible++;
                        }
                }
                else if(Ci->getGate(gi)->inputSize() == 3)
                {
                        c3++;
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria/2)
                        {
                                cnt_three_in++;
                                Ci->getGate(gi)->correlated++;
                        }
                }
                else
                        c1++;
        }
        
        cout<<"total number of gates is "<<Ci->gateSize()<<endl;
        cout<<"# of one-input gates is "<<c1<<endl;
        cout<<"# of two-inputs gates is "<<c2<<endl;

        cout<<"# of three-inputs gates is "<<c3<<endl;
        cout<<"# of correlated two-inputs gates is "<<cnt_two_in<<endl;
        cout<<"# of impossible two-inputs gates is "<<impossible<<endl;
        cout<<"# of correlated three-inputs gates is "<<cnt_three_in<<endl;
        
	return;
}

bool Simulate::PreSimHybrid1Trace()
{
        list<Signal*> sigList;
	bool cont=false;
        string DFF_Under_Sim;
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                if(Ci->getSignal(i)->untouchible == true)
                {
                        for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                                assert(Ci->getSignal(i)->valArray[j] != Z);
                        if(Ci->getSignal(i)->valArray[0] == 1)
                                Ci->getSignal(i)->setVal(One);
                        else
                                Ci->getSignal(i)->setVal(Zero);
                        sigList.push_back(Ci->getSignal(i));
                }
        }
        
        Signal *s;
	while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                
                if(s->stored == 1)
                        continue;
#ifdef DEBUG_SIMULATE
                cout<<"Current signals in list are"<<endl;
                for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                        cout<<(*it)->getName()<<"\t";
                cout<<endl;
                
                cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                cin.get();
#endif
                s->stored = 1;
                
                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                                
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;
                                                
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }

                                        if(s->getOutput(i)->isActive()){
                                                
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                        
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                           sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        return cont;
}

bool Simulate::simHybrid1Trace(bool test)
{
        int Cmark = 0;
        list<Signal*> sigList;
	bool cont=false;
        string DFF_Under_Sim;
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                if(Ci->getSignal(i)->untouchible == true)
                {
                        for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                                assert(Ci->getSignal(i)->valArray[j] != Z);
                        if(Ci->getSignal(i)->valArray[0] == 1)
                                Ci->getSignal(i)->setVal(One);
                        else
                                Ci->getSignal(i)->setVal(Zero);
                        sigList.push_back(Ci->getSignal(i));
                }
        }

        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced())
                {
                        DFF_Under_Sim = Ci->getFlipflop(i)->getOutput(0)->getName();
                        if(test == true){
                                Ci->getFlipflop(i)->getOutput(0)->setVal(One);
                        }
                        else{
                                Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
                        }
                        Ci->getFlipflop(i)->setInput();
                        sigList.push_back(Ci->getFlipflop(i)->getInput(1));
			sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        //if(DFF_Under_Sim == "P1_state")
        //Cmark = 1;
                
        Signal *s;
	while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                
                if(s->stored == 1)
                        continue;
#ifdef DEBUG_SIMULATE
                if(Cmark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
                }
#endif                
                s->stored = 1;
                
                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                                
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;
                                                
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }

                                        if(s->getOutput(i)->isActive()){
                                                
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                        
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                           sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        return cont;
}

double probAdjust(Signal* s, double Pbar)
{
        return ((1 - s->Cur_P > Pbar)? Pbar : 1 - s->Cur_P);
}

double probAdjustGate(Node* n, Signal* s, double Pbar)
{
        return ((n->weight - s->Cur_P > Pbar)? Pbar : n->weight - s->Cur_P);
}

double probAdjustBack(Signal* s, double Pbar)
{
        if(s->Cur_P > 1.0)
                return 0.0;
        else
                return ((s->Cur_P > Pbar)? Pbar : s->Cur_P);
}

double Simulate::huerSelect2ProcessFor1(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;

        while(i != trace_size)
        {
                weight = 0.0;
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight = (*it_map)->R0.size() * (*it_map)->P0 + 
                                (*it_map)->R1.size() * (*it_map)->P1;
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 0.0)
                        break;
              
                //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;

                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                {
                        if(it_map != it_map1)
                        {
                                for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                                {
                                        it_set1 = (*it_map)->R0.find(*it_set);
                                        if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= (*it_map1)->P0)
                                                (*it_map)->R0.erase(it_set1);
                                        
                                        it_set1 = (*it_map)->R1.find(*it_set);
                                        if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= (*it_map1)->P0)
                                                (*it_map)->R1.erase(it_set1);
                              
                                }
                                
                                for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                                {
                                        it_set1 = (*it_map)->R1.find(*it_set);
                                        if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= (*it_map1)->P1)
                                                (*it_map)->R1.erase(it_set1);
                                
                                        it_set1 = (*it_map)->R0.find(*it_set);
                                        if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= (*it_map1)->P1)
                                                (*it_map)->R0.erase(it_set1);
                                }
                        }
                }

                Mymap.erase(it_map1);
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

bool moreVNSAMPLE(sample s1, sample s2)
{
        return(s1.VN > s2.VN);
}

bool rateMapSort(mapRate a1, mapRate a2)
{
        return (a1.weight > a2.weight);
}

bool TrateMapSort(TmapRate a1, TmapRate a2)
{
        return (a1.weight > a2.weight);
}

double Simulate::huerSelect2ProcessFor2(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces, const char* filename){
        
        int i, j;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<mapRate> MR;
        assert(selected_traces.size() == 0);
        
        cout<<"file name is "<<filename<<endl;        
        ofstream report(filename);
        report<<Ci->flipflopSize()<<endl;
        
        struct timeval start1, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                MR.clear();
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                        
                        mapRate myMR;
                        myMR.weight = temp_weight;
                        myMR.it_map = it_map;                
                        MR.push_back(myMR);
                }
                
                if(weight == 0.0)
                        break;
              
                std::sort(MR.begin(), MR.end(), rateMapSort);
                
                double largest_weight = MR[0].weight;
                const double topK = 0.05;
                for(j = 0; j < MR.size(); j++)
                {
                        if(MR[j].weight < topK * largest_weight)
                                break;
                        
                        MR[j].weight = 0.0;
                }
                
                assert(j != 0);
                
                if(selected_traces.size() == 0)
                        j = 100;
                
                if( selected_traces.size() > 0 && j > 50 )
                        j = 50;
                
                if(j > MR.size())
                        j = MR.size();
                else
                        MR.resize(j);
                
                cout << "j is " << j << endl;
                const int thread_num = j;
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        for(i=0; i < Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i < selected_traces.size(); ++i)
                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                        Ci->getFlipflop((*(MR[j].it_map))->DFF_id)->getOutput(0)->setTraced(true,j);
                }
                
                int seed_num = 0;
                while(seed_num < 2)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                LoadInitDFFValue(10 + seed_num * 10, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                                
                                //cout<<"Tid is "<<mra->Tid + pos<<endl;
                                MR[mra->Tid].weight += mra->VN;
                                delete mra;
                        }
                        
                        seed_num++;
                }
                
                for(j = 0; j < thread_num; j++)
                        cout << (*(MR[j].it_map))->DFF_id << " 's restorability is " << MR[j].weight << endl; 

                //cin.get();
                
                cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
                std::sort(MR.begin(), MR.end(), rateMapSort);
                
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop((*(MR[0].it_map))->DFF_id)->getOutput(0)->getName() << endl;
                
                cout<<"VN is "<<MR[0].weight / 2 <<endl;
                selected_traces.push_back((*(MR[0].it_map))->DFF_id);
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double cur_VN = MultCalVNWOLOCK(0);
                
                double restime = 0.0;
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                        Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                it_map1 = MR[0].it_map;
                Mymap.erase(it_map1);
                
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, cur_VN);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish3, NULL);

                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                }        
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect2ProcessFor2Com(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces, const char* filename){
        
        int i, j;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;

        vector<mapRate> MR;
        assert(selected_traces.size() == 0);
        
        cout<<"file name is "<<filename<<endl;        
        ofstream report(filename);
        report<<Ci->flipflopSize()<<endl;
        
        clock_t start1, finish1, finish2, finish3;
        start1 = clock();
        
        while(selected_traces.size() < trace_size)
        {
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }        
                }
                
                if(weight == 0.0)
                        break;
              
                selected_traces.push_back((*it_map1)->DFF_id);
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double cur_VN = MultCalVNWOLOCK(0);
                
                double restime = 0.0;
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                        Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                //The current commented area is for the case when there is
                //no simulation help for restoration demand adjustment
                Mymap.erase(it_map1);
                
                if(selected_traces.size() == 8)
                {
                        finish1 = clock();

                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( (finish1 - start1) / CLOCKS_PER_SEC ) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( (finish1 - start1) / CLOCKS_PER_SEC ) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        //addIslands(selected_traces, cur_VN);
                }
                
                if(selected_traces.size() == 16)
                {
                        finish2 = clock();
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;

                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        //addIslands(selected_traces, cur_VN);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, cur_VN);
                
                if(selected_traces.size() == 32)
                {
                        finish3 = clock();
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;

                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                }        
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}


double probAdjust2(Signal* s, const double Pbar, const int val)
{
        assert(val != 2);
        if(val == 1)
                return ((1 - s->Cur_P1 > Pbar)? Pbar : 1 - s->Cur_P1);
        else
                return ((1 - s->Cur_P0 > Pbar)? Pbar : 1 - s->Cur_P0);
}

double probAdjustBack2(Signal* s, const double Pbar, const int val)
{
        assert(val != 2);
        if(val == 1)
        {
                if(s->Cur_P1 > 1.0)
                        return 0.0;
                else
                        return ((s->Cur_P1 > Pbar)? Pbar : s->Cur_P1);
        }
        else
        {
                if(s->Cur_P0 > 1.0)
                        return 0.0;
                else
                        return ((s->Cur_P0 > Pbar)? Pbar : s->Cur_P0);
        }
}

double Simulate::huerSelect2ProcessFor2Mod(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0, j;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        vector<resVal>::iterator it_set;
        vector<resVal>::iterator it_set1;
        vector<int>::iterator it_vec;

        vector<mapRate> MR;
        while(i != trace_size)
        {
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0_P.begin(); it_set != (*it_map)->R0_P.end(); it_set++)
                                temp_weight += probAdjust2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), 
                                                           (*it_map)->P0, (*it_set).val);
                        
                        for(it_set = (*it_map)->R1_P.begin(); it_set != (*it_map)->R1_P.end(); it_set++)
                                temp_weight += probAdjust2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), 
                                                           (*it_map)->P1, (*it_set).val);
                        
                        mapRate myMR;
                        myMR.weight = temp_weight;
                        myMR.it_map = it_map;
                }
                
                if(weight == 0.0)
                        break;
                
                std::sort(MR.begin(), MR.end(), rateMapSort);
                
                double largest_weight = MR[0].weight;
                const double topK = 0.1;
                for(j = 0; j < MR.size(); j++)
                {
                        if(MR[j].weight < topK * largest_weight)
                                break;
                        
                        MR[j].weight = 0.0;
                }
                
                assert(j != 0);
                MR.resize(j);

                const int thread_num = j;
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        for(i=0; i<Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,j);
                                }
                        }
                }
                
                int seed_num = 0;
                while(seed_num < 3)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                LoadInitDFFValue(50 + seed_num * 150, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                                MR[mra->Tid].weight += mra->VN;
                                delete mra;
                        }
                                
                        seed_num++;
                }
                
                std::sort(MR.begin(), MR.end(), rateMapSort);
                i++;
                
                it_map1 = MR[j].it_map;
                for(it_set = (*it_map1)->R0_P.begin(); it_set != (*it_map1)->R0_P.end(); it_set++)
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map1)->P0;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map1)->P0;
                
                for(it_set = (*it_map1)->R1_P.begin(); it_set != (*it_map1)->R1_P.end(); it_set++)
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map1)->P1;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map1)->P1;
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P0 > 1.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P0 = 1.0;
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P1 > 1.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P1 = 1.0;
                }
                
                Mymap.erase(it_map1);
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect2ProcessBack(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                assert(Ci->getFlipflop(j)->getOutput(0)->Cur_P == 0.0);
        //calculating the summation of all
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P += (*it_map)->P0;
                
                for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P += (*it_map)->P1;
        }
        
        //assert(islands.size() != 0);
        int prune_start_num = Ci->flipflopSize() - islands.size();
        while(prune_start_num - i != trace_size)
        {
                weight = 1.0e20;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                temp_weight += probAdjustBack(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                temp_weight += probAdjustBack(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        if(temp_weight < weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 1.0e20)
                        break;
              
                //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;

                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P -= (*it_map1)->P0;
                
                for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P -= (*it_map1)->P1;
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P < 0.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P = 0.0;
                
                Mymap.erase(it_map1);
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(true,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(false,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        for(i = 0; i < islands.size(); i++)
                Ci->getFlipflop(islands[i])->getOutput(0)->setTraced(false,0);

        cout<<"selected DFFs are"<<endl;
        selected_traces.clear();
        for(int j=0; j < Ci->flipflopSize(); ++j)
                if(Ci->getFlipflop(j)->getOutput(0)->getTraced(0) == true)
                {
                        cout<<Ci->getFlipflop(j)->getOutput(0)->getName()<<"\t";
                        selected_traces.push_back(j);
                }
        cout<<endl;

        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect2ProcessBackMod(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        vector<resVal>::iterator it_set;
        vector<resVal>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
        {
                assert(Ci->getFlipflop(j)->getOutput(0)->Cur_P0 == 0.0);
                assert(Ci->getFlipflop(j)->getOutput(0)->Cur_P1 == 0.0);
        }
                
        //calculating the summation of all
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                for(it_set = (*it_map)->R0_P.begin(); it_set != (*it_map)->R0_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map)->P0;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map)->P0;
                }
                
                for(it_set = (*it_map)->R1_P.begin(); it_set != (*it_map)->R1_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map)->P1;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map)->P1;
                }
                
        }
        
        //assert(islands.size() != 0);
        int prune_start_num = Ci->flipflopSize() - islands.size();
        while(prune_start_num - i != trace_size)
        {
                weight = 1.0e20;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0_P.begin(); it_set != (*it_map)->R0_P.end(); it_set++)
                                temp_weight += probAdjustBack2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), (*it_map)->P0, (*it_set).val);
                        
                        for(it_set = (*it_map)->R1_P.begin(); it_set != (*it_map)->R1_P.end(); it_set++)
                                temp_weight += probAdjustBack2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), (*it_map)->P1, (*it_set).val);
                        
                        if(temp_weight < weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 1.0e20)
                        break;
              
                //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;

                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_set = (*it_map1)->R0_P.begin(); it_set != (*it_map1)->R0_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 -= (*it_map1)->P0;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 -= (*it_map1)->P0;
                }
                
                for(it_set = (*it_map1)->R1_P.begin(); it_set != (*it_map1)->R1_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 -= (*it_map1)->P1;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 -= (*it_map1)->P1;
                }
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P < 0.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P = 0.0;
                
                Mymap.erase(it_map1);
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(true,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(false,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        for(i = 0; i < islands.size(); i++)
                Ci->getFlipflop(islands[i])->getOutput(0)->setTraced(false,0);

        cout<<"selected DFFs are"<<endl;
        selected_traces.clear();
        for(int j=0; j < Ci->flipflopSize(); ++j)
                if(Ci->getFlipflop(j)->getOutput(0)->getTraced(0) == true)
                {
                        cout<<Ci->getFlipflop(j)->getOutput(0)->getName()<<"\t";
                        selected_traces.push_back(j);
                }
        cout<<endl;

        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect3Process(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        map<int,double>::iterator it_RM;
        map<int,double>::iterator it_RM1;
        vector<int>::iterator it_vec;

        while(i != trace_size)
        {
                weight = 0.0;
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight = (*it_map)->R.size();
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 0.0)
                        break;
              
                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                {
                        if(it_map != it_map1)
                        {
                                for(it_RM = (*it_map1)->R.begin(); it_RM != (*it_map1)->R.end(); it_RM++)
                                {
                                        it_RM1 = (*it_map)->R.find((*it_RM).first);
                                        if(it_RM1 != (*it_map)->R.end())//&& (*it_RM1).second <= (*it_RM).second)
                                                (*it_map)->R.erase(it_RM1);
                                }
                        }
                }

                Mymap.erase(it_map1);
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

bool moreFanouts(Signal* a, Signal* b)
{
        return (a->outputs.size() > b->outputs.size());
}

void Simulate::PickTop3MostFanout(){
        
        vector<Signal*> sigList;
        for(int i=0; i<Ci->signalSize(); ++i)
                sigList.push_back(Ci->getSignal(i));
        
        std::sort(sigList.begin(),sigList.end(),moreFanouts);
        
        for(int i = 0; i < 8; i++)
                cout<<sigList[i]->getName()<<"\t";
        cout<<endl;
}

void Simulate::SetProb(){
        
        int count0, count1;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                count0 = 0; count1 = 0;
                for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                {
                        assert(Ci->getFlipflop(i)->getOutput(0)->valArray[j] != 2);
                        if(Ci->getFlipflop(i)->getOutput(0)->valArray[j] == 1)
                                count1++;
                        else
                                count0++;
                }
                
                Ci->getFlipflop(i)->getOutput(0)->setP0((double)count0 / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE))) );
                Ci->getFlipflop(i)->getOutput(0)->setP1((double)count1 / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE))) );
        }
        
}

void Simulate::updateRStime(){
}

void Simulate::updateRSmapWeight(vector<resMap*> &Mymap)
{
        double temp_total;
        map<int,double>::iterator it_RM;
        vector<resMap*>::iterator it_map;
        for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
        {
                (*it_map)->weight = 0.0;
                temp_total = 0.0;
                for(it_RM = (*it_map)->R.begin(); it_RM != (*it_map)->R.end(); it_RM++)
                {
                        if(Ci->getSignal((*it_RM).first)->RStime == 0)
                                temp_total += 1;
                        else
                                temp_total += (double)1/Ci->getSignal((*it_RM).first)->RStime;
                }
                
                //(*it_map)->weight += temp_total;
                (*it_map)->weight += temp_total;
                //(*it_map)->weight += (*it_map)->P1 * temp_total;
        }
}

bool moreSecondWeight(Signal* a, Signal* b)
{
        return (a->weight > b->weight);
}

bool moreRSWeight(resMap* a, resMap* b)
{
        return (a->weight > b->weight);
}

bool Simulate::DFS_Forward(Node* ni, const int DFF_id, vector<Node*>& PassedNodes)
{
        for(int i = 0; i < ni->outputSize(); i++)
        {
                for(int j = 0; j < ni->getOutput(i)->outputSize(); j++)
                {
                        
                        if(ni->getOutput(i)->getOutput(j)->visited == true)
                                continue;
                        
                        if(ni->getOutput(i)->getOutput(j)->signature() == FLIPFLOP)
                        {
                                if(std::find(Ci->getFlipflop(DFF_id)->nearbyDFFs.begin(), 
                                             Ci->getFlipflop(DFF_id)->nearbyDFFs.end(), 
                                             ((FlipflopNode*)ni->getOutput(i)->getOutput(j))->FF_index) == Ci->getFlipflop(DFF_id)->nearbyDFFs.end())
                                        Ci->getFlipflop(DFF_id)->nearbyDFFs.push_back(((FlipflopNode*)ni->getOutput(i)->getOutput(j))->FF_index);
                        }
                        else
                        {
                                ni->getOutput(i)->getOutput(j)->visited = true;
                                PassedNodes.push_back(ni->getOutput(i)->getOutput(j));
                                DFS_Forward(ni->getOutput(i)->getOutput(j), DFF_id, PassedNodes);
                        }
                }        
        }

        return true;
}

bool Simulate::DFS_Backward(Node* ni, const int DFF_id, vector<Node*>& PassedNodes)
{
        for(int i = 0; i < ni->inputSize(); i++)
        {
                for(int j = 0; j < ni->getInput(i)->inputSize(); j++)
                {
                        if(ni->getInput(i)->getInput(j)->signature() == FLIPFLOP)
                        {
                                if(std::find(Ci->getFlipflop(DFF_id)->nearbyDFFs.begin(), 
                                             Ci->getFlipflop(DFF_id)->nearbyDFFs.end(), 
                                             ((FlipflopNode*)ni->getInput(i)->getInput(j))->FF_index) == Ci->getFlipflop(DFF_id)->nearbyDFFs.end())
                                        Ci->getFlipflop(DFF_id)->nearbyDFFs.push_back(((FlipflopNode*)ni->getInput(i)->getInput(j))->FF_index);
                        }
                        else
                        {
                                ni->getInput(i)->getInput(j)->visited = true;
                                PassedNodes.push_back(ni->getInput(i)->getInput(j));
                                DFS_Forward(ni->getInput(i)->getInput(j), DFF_id, PassedNodes);
                        }
                }
        }

        return true;
}

void Simulate::DFFSearchNearby(){
        
        vector<Node*> PassedNodes;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                PassedNodes.clear();
                DFS_Forward(Ci->getFlipflop(i), i, PassedNodes);
                DFS_Backward(Ci->getFlipflop(i), i, PassedNodes);
                
                for(int j = 0; j < PassedNodes.size(); j++)
                        PassedNodes[j]->visited = false;
                
                Ci->getFlipflop(i)->visited = true;
                assert(Ci->getFlipflop(i)->nearbyDFFs.size() != 0);
        }
        
}

void Simulate::Sample_Procedure(const int sample_times){
        
        srand ( time(NULL) );
        const int thread_max = 24;
        vector<sample> mySamples;
        
        int i, j, pos = 0;
        while(pos < sample_times)
        {
                int thread_num = (sample_times-pos >= thread_max)? thread_max : (sample_times-pos);
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        sample MS;
                        for(i=0; i<Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,j);
                                        MS.DFF_ids.push_back(i);
                                        
                                        int try_time = 0;
                                        while(try_time < 20)
                                        {
                                                int num = rand()%Ci->getFlipflop(i)->nearbyDFFs.size();
                                                if(Ci->getFlipflop(num)->getOutput(0)->getTraced(j) == false)
                                                {
                                                        MS.DFF_ids.push_back(num);
                                                        Ci->getFlipflop(num)->getOutput(0)->setTraced(true,j);
                                                        break;
                                                }
                                                
                                                try_time++;
                                        }
                                }
                        }
                        
                        MS.VN = 0.0;
                        mySamples.push_back(MS);
                }
                
                int seed_num = 0;
                while(seed_num < 3)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;//should add pos later
                                mwa->Sim = this;
                                LoadInitDFFValue(50 + seed_num * 150, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                                
                                //cout<<"Tid is "<<mra->Tid + pos<<endl;
                                mySamples[mra->Tid + pos].VN += mra->VN;                                
                                delete mra;
                        }
                                
                        seed_num++;
                }
                
                pos += thread_num;
        }
        
        std::sort(mySamples.begin(), mySamples.end(), moreVNSAMPLE);
        for(i = 0; i < mySamples[0].DFF_ids.size(); i++)       
        {
                int id = mySamples[0].DFF_ids[i];
                Ci->getFlipflop(id)->getOutput(0)->chosen = true;       
        }
}

void Simulate::addIslands(vector<int> &selected_traces, double VN_bar){
        
        int i, j;
        int thread_num = islands.size();
        cout<< "island's size is " << thread_num << endl;
        pthread_t PTs[thread_num];
        vector<sample> mySamples;
        
        for(j = 0; j < thread_num; j++)
        {
                sample MS;
                for(i=0; i < Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                
                for(i=0; i < selected_traces.size(); ++i)
                        Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                
                Ci->getFlipflop(islands[j])->getOutput(0)->setTraced(true,j);
                
                MS.VN = 0.0;
                MS.DFF_ids.push_back(islands[j]);
                mySamples.push_back(MS);
        }
        
        int seed_num = 0;
        while(seed_num < 2)
        {
                initMultThread(thread_num);
                
                for(j = 0; j < thread_num; j++)
                {
                        myWorkarg* mwa= new myWorkarg;
                        mwa->Tid = j;
                        mwa->Sim = this;
                        LoadInitDFFValue(50 + seed_num * 150, j);
                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                }
                
                for(j = 0; j < thread_num; j++)
                {
                        myRetarg* mra = new myRetarg;
                        pthread_join(PTs[j], (void**) &mra);
                        
                        //cout<<"Tid is "<<mra->Tid + pos<<endl;
                        mySamples[mra->Tid].VN += mra->VN;
                        delete mra;
                }
                
                seed_num++;
        }
                
        //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
        std::sort(mySamples.begin(), mySamples.end(), moreVNSAMPLE);
        
        const double threshold = 10.0;
        for(i = 0; i < mySamples.size(); i++)       
        {
                if(mySamples[i].VN / 2 - VN_bar < threshold)
                        break;
        }
        
        if(i == 0)
                cout << "no other selected" << endl;
        else
        {
                i = 2;
                cout << "added islands flipflop num is " << i << endl;
        }
        
        for(j = 0; j < i; j++)
        {
                selected_traces.push_back(mySamples[j].DFF_ids[0]);
                islands.erase(std::find(islands.begin(), islands.end(), mySamples[j].DFF_ids[0]));
        }
        
        for(i=0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(i=0; i < selected_traces.size(); ++i)
                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,0);
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        cout<<"After adding islands, VN is "<< MultCalVNWOLOCK(0) <<endl;        
        double restime = 0.0;
        for(j = 0; j < Ci->flipflopSize(); ++j)
        {
                restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        }
}

extern int HeuTry;
void Simulate::hueristicSelect2(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        double weight, temp_weight, cur_VN;
        vector<resMap*> Mymap;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        map< string, resMap* > RSmap;

        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_heu";
        
        //ofstream report(tmp.c_str());
        //report<<Ci->flipflopSize()<<endl;
        
        clock_t start1, finish1, start2, finish2;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        initSimulate();
        //SimInitDFFValue();
        LoadDFFMap(filename);
        start1 = clock();
        
        //finish collecting resMap
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                flag = 0;
                resMap* MyresMap = new resMap;
                clearTraced();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                addTraced(Ci->getFlipflop(i)->getOutput(0));
                
                assert(tracedSigs.size() == 1);
                
                MyresMap->DFF_id = i;
                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->getP0();
                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->getP1();
                
                if(MyresMap->P0 == 0.0 && MyresMap->P1 == 0.0)
                {
                        cout<<"no Way!"<<endl;
                        cout<<"the signal name is "<<Ci->getFlipflop(i)->getOutput(0)->getName()<<endl;
                }
                //initSimulateGolden();
                //initSimulateHybrid();
                //sim_event(true);
                //sim_event(false);
                
                initSimulateHybrid();
                PreSimHybrid1Trace();
                
                for(k = 0; k<Ci->flipflopSize(); ++k)
                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                simHybrid1Trace(true);
                
                int count_res1 = 0;
                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R1.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R1_P.push_back(RV);
                                        count_res1++;
                                }
                
                //cout<<"# of DFFs stored when "<< Ci->getFlipflop(i)->getOutput(0)->getName() << " has value 1 is "
                //<< count_res1 << endl;
                
                //initSimulateGolden();
                //initSimulateHybrid();
                //sim_event(true);
                //sim_event(false);

                initSimulateHybrid();
                PreSimHybrid1Trace();
                
                for(k = 0; k<Ci->flipflopSize(); ++k)
                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                simHybrid1Trace(false);
                
                int count_res0 = 0;
                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R0.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;

                                        MyresMap->R0_P.push_back(RV);
                                        count_res0++;
                                }
                
                //cout<<"# of DFFs stored when "<< Ci->getFlipflop(i)->getOutput(0)->getName() << " has value 0 is "
                //<< count_res0 << endl;
                
                //cin.get();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                
                if(flag == 1)
                {
                        RSmap.insert(pair<string, resMap*>(Ci->getFlipflop(i)->getOutput(0)->getName(), MyresMap) );
                        Mymap.push_back(MyresMap);
                }
                else
                        islands.push_back(i);
        }
        finish1 = clock();
        
        vector<resMap*> Mymap_Ori(Mymap);
        
        if(filename == NULL)
        {
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        cout<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        cout<<"restored DFF from 0"<<endl;
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                cout<<*it_set<<"\t";
                        cout<<endl;
                        
                        cout<<"restored DFF from 1"<<endl;
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                cout<<*it_set<<"\t";
                        cout<<endl;
                }
        }
        else
        {
                cout<<"filename is "<<filename <<endl;
                //cin.get();
                ofstream out(filename);
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        out<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0)->getName()<<"\t"<<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        out<<"restored DFF from 0 size is "<<(*it_map)->R0.size()<<endl;
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                out<<*it_set<<"\t";
                        out<<endl;
                
                        out<<"restored DFF from 1 size is "<<(*it_map)->R1.size()<<endl;
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                out<<*it_set<<"\t";
                        out<<endl;
                }
        }
        
        start2 = clock();
        cout<<"The time spend on generating the reachibility list is "<< ( (finish1 - start1)/CLOCKS_PER_SEC )<<endl;
        //cout<<"Should be added later!"<<endl;
        //cur_VN = huerSelect2ProcessFor1(trace_size, Mymap, selected_traces);
        cur_VN = huerSelect2ProcessFor2(trace_size, Mymap, selected_traces, tmp.c_str());
        //cur_VN = huerSelect2ProcessFor2Com(trace_size, Mymap, selected_traces, tmp.c_str());
        //cur_VN = huerSelect2ProcessFor2Mod(trace_size, Mymap, selected_traces);
        //cur_VN = huerSelect2ProcessBack(trace_size, Mymap, selected_traces);
        //cur_VN = huerSelect2ProcessBackMod(trace_size, Mymap, selected_traces);
        cout<<"Initial VN is "<<cur_VN<<endl;
        //return;

        vector<int> final_traces;
        vector<int> root_traces(selected_traces);
        /*
        vector<Signal*>::iterator it;
        cout<< "selected_traces size is "<<selected_traces.size()<<endl;
        cout<<"trace size is "<<trace_size<<endl;
        cout<<"island size is "<<islands.size()<<endl;
        
        //find the neighbour of the flipflops 
        for(int i =0 ; i < selected_traces.size(); i++)
                Ci->getFlipflop(selected_traces[i])->getOutput(0)->chosen = true;
        
        DFFSearchNearby();
        Sample_Procedure(200);
        //Sample_Procedure(200);
        //Sample_Procedure(100);
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        int count_chosen = 0;
        for(i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                {
                        count_chosen++;
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                }
        
        cout<<"Chosen number of flipflops is "<<count_chosen<<endl;
        
        double temp_VN;
        temp_VN = MultComputVN(0);        
        cout<< "#VN : " << temp_VN <<endl;
        return;
        */
        /*
        const int insert_num = 20;
        for(i = 0; i < insert_num; i++)
        {
                lessRSedSignals[i]->setTraced(true);
        }
        
        
        tracedSigs.clear();
        for(i = 0; i < Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced() == true)
                        tracedSigs.push_back(Ci->getFlipflop(i)->getOutput(0));
        
        Conf* c1;
        Confset* C1;
        vector<Signal*>::iterator it;
        cout<<"trace sig size is "<<tracedSigs.size()<<endl;
        cout<<"trace size is "<<trace_size<<endl;
        while(tracedSigs.size() > trace_size)
        {
                C1 = new Confset();
                for(i = 0; i < tracedSigs.size(); i++)
                {
                        tracedSigs[i]->setTraced(false);
                        c1 = new Conf();
                        c1->tracedSigs.push_back(tracedSigs[i]);
                        
                        initMultThread(1);
                        LoadInitDFFValue(0);
                        c1->TV = MultCalVN(0);
                        
                        c1->TVNC = c1->TV;
                        C1->confs.push_back(c1);
                        tracedSigs[i]->setTraced(true);
                }
                
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                it = find(tracedSigs.begin(), tracedSigs.end(), C1->confs[0]->tracedSigs[0]);
                assert( it != tracedSigs.end() );
                
                (*it)->setTraced(false);
                tracedSigs.erase(it);
                
                C1->~Confset();
        }
        
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                cout<<(*it)->getName()<<"\t";
        }
        cout<<endl;
        */
        
        double temp_VN = cur_VN;
        //temp_VN = computVN();
        //temp_VN = MultComputVN(0);
        //temp_VN = exhaustiveComputVN(true);
        cout<< "#VN : " << temp_VN <<endl;
        
        //addIslands(selected_traces, temp_VN);

        /*
        double temp_P;
        int j = 0;
        for(it_vec = root_traces.begin(); it_vec != root_traces.end() && j <= HeuTry; it_vec++){
                
                j++; i = 0;
                selected_traces.clear();
                Mymap = Mymap_Ori;
                
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        if((*it_map)->DFF_id == *it_vec)
                        {
                                it_map1 = it_map;
                                break;
                        }
                
                while(i != trace_size)
                {
                        i++;
                        //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
                        selected_traces.push_back((*it_map1)->DFF_id);
                        for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        {
                                if(it_map != it_map1)
                                {
                                        for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                                        {
                                                //if the DFF can be
                                                //restored from both 0 and 1
                                                if((*it_map)->R1.find(*it_set) != (*it_map)->R1.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P0;
                                                
                                                it_set1 = (*it_map)->R0.find(*it_set);                                                                
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                                
                                        }
                                        
                                        for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                                        {
                                                if((*it_map)->R0.find(*it_set) != (*it_map)->R0.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P1;
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                
                                                it_set1 = (*it_map)->R0.find(*it_set);
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                        }
                                }
                        }
                        
                        Mymap.erase(it_map1);
                        
                        weight = 0.0;
                        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                        {
                                temp_weight = (*it_map)->R0.size() * (*it_map)->P0 + 
                                        (*it_map)->R1.size() * (*it_map)->P1;
                        
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                        }
                
                        if(weight == 0.0)
                                break;
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
                
                tracedSigs.clear();
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                        tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
                }
                
                //double temp_VN = computVN();
                //double temp_VN = exhaustiveComputVN();
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double temp_VN = MultCalVNWOLOCK(0);
                //double temp_VN = MultComputVN(0);
                if(temp_VN > cur_VN)
                {
                        cur_VN = temp_VN;
                        swap(final_traces,selected_traces);
                }
        }
        finish2 = clock();
        */
        /*
        report<<"total runtime for DFF Simulation is: "<<( (finish1 - start1)/CLOCKS_PER_SEC )<<endl;
        report<<"total runtime for Heuristic Selection is: "<<( (finish2 - start2)/CLOCKS_PER_SEC )<<endl;
        report<<final_traces.size()<<endl;
        report<<"seleted signals are...."<<endl;
        
        cout<<"seleted signals are...."<<endl;
        for(it_vec = final_traces.begin(); it_vec != final_traces.end(); it_vec++)
        {
        report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        }
        cout<<endl;
        report<<endl;
        
        report<<selected_traces.size()<<endl;
        cout<<"seleted signals are...."<<endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
        {
                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        }
        cout<<endl;
        report<<endl;
        
        cout<<"Visibility is "<<cur_VN<<endl;
        report<<cur_VN<<endl;
        report.close();
        */
}

bool lessRestoredMap(resMap* a1, resMap *a2)
{
        return (a1->R.size() < a2->R.size());
}

void Simulate::hueristicSelect3(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        double weight, temp_weight, cur_VN;
        vector<resMap*> Mymap;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        map< string, resMap* > RSmap;
        
        map<int,double>::iterator it_RM;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        i = 0;
        while(tmp.c_str()[i] != 'b')
                i++;
        tmp.erase(tmp.begin()+i,tmp.end());
        tmp += "report_heu";
        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        
        clock_t start1, finish1, start2, finish2;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        //PickTop3MostFanout();
        
        initSimulate();
        SimInitDFFValue();
        //SetProb();
        start1 = clock();
        //finish collecting resMap
        cout<<"FLipflop size is "<<Ci->flipflopSize()<<endl;
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                flag = 0;
                resMap* MyresMap = new resMap;
                clearTraced();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                addTraced(Ci->getFlipflop(i)->getOutput(0));
                
                assert(tracedSigs.size() == 1);
                
                MyresMap->DFF_id = i;
                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->getP0();
                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->getP1();
                
                if(MyresMap->P0 == 0.0 && MyresMap->P1 == 0.0)
                {
                        cout<<"no Way!"<<endl;
                        cout<<"the signal name is "<<Ci->getFlipflop(i)->getOutput(0)->getName()<<endl;
                }
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                MultCalVN(0);
                
                //int count_res1 = 0;
                int restime = 0;
                for(k =0; k<Ci->flipflopSize(); ++k)
                {
                        if(Ci->getFlipflop(k)->getOutput(0)->getTraced(0) == true)
                                continue;
                        
                        restime = Ci->getFlipflop(k)->getOutput(0)->isMultKnown(0);
                        if(restime != 0)
                        {
                                flag = 1;
                                MyresMap->R[k] = (double)restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                //count_res1++;
                        }
                }
                
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
                
                if(flag == 1)
                {
                        RSmap.insert(pair<string, resMap*>(Ci->getFlipflop(i)->getOutput(0)->getName(), MyresMap) );
                        Mymap.push_back(MyresMap);
                }
                else
                        islands.push_back(i);
        }
        finish1 = clock();
        
        vector<resMap*> Mymap_Ori(Mymap);
        /*
        if(filename == NULL)
        {

        }
        else
        {
                cout<<"filename is "<<filename <<endl;
                //cin.get();
                ofstream out(filename);
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        out<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<"Name\t" << Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0)->getName()<<"\t"
                           <<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        out<<"restored DFF size is "<<(*it_map)->R.size()<<endl;
                        for(it_RM = (*it_map)->R.begin(); it_RM != (*it_map)->R.end(); it_RM++)
                                out<<(*it_RM).first<<"\t";
                        out<<endl;
                
                }
        }
        */
        start2 = clock();
        cur_VN = huerSelect3Process(trace_size, Mymap, selected_traces);
        cout<<"Initial VN is "<<cur_VN<<endl;
        /*
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(0) == true)
                {
                        for(int j = 0; j < 8*sizeof(myDataType); j++)
                                cout<<Ci->getFlipflop(i)->getOutput(0)->valArray[j]<<"\t";
                        cout<<endl;
                }
        }
        cin.get();
        */
        
        // double temp_VN;
        // int count = 0;
        // while(1)
        // {
        //         updateRStime();
        //         Mymap = Mymap_Ori;
        //         updateRSmapWeight(Mymap);
        //         std::sort(Mymap.begin(), Mymap.end(), moreRSWeight);
                
        //         for(int i = 0; i < Mymap.size(); i++)
        //                 if(Ci->getFlipflop(Mymap[i]->DFF_id)->getOutput(0)->getTraced(0) == false)
        //                 {
        //                         cout<<"added flipflop name is "
        //                             <<Ci->getFlipflop(Mymap[i]->DFF_id)->getOutput(0)->getName()<<endl;
        //                         Ci->getFlipflop(Mymap[i]->DFF_id)->getOutput(0)->setTraced(true,0);
        //                         break;
        //                 }
                
        //         //initMultThread(1);
        //         LoadInitDFFValue(0,0);
        //         temp_VN = MultCalVNWOLOCK(0);
        //         cout<<"temp_VN is "<<temp_VN<<endl;
                
        //         count++;
        //         if(count == 40)
        //                 break;
        //         /*
        //         if(temp_VN > cur_VN)
        //                 cur_VN = temp_VN;
        //         else
        //                 break;
        //         */
        // }
        
        // temp_VN = MultComputVN(0);
        // cout<<"#VN is "<<temp_VN<<endl;
        
        vector<int> final_traces;
        vector<int> root_traces(selected_traces);
        
        Conf* c1;
        Confset* C1;
        vector<Signal*>::iterator it;
        cout<<"trace sig size is "<<tracedSigs.size()<<endl;
        cout<<"trace size is "<<trace_size<<endl;
        cout<<"island size is "<<islands.size()<<endl;
        
        //find the neighbour of the flipflops 
        for(int i =0 ; i < selected_traces.size(); i++)
                tracedSigs[i]->chosen = true;
        
        DFFSearchNearby();
        Sample_Procedure(100);
        //Sample_Procedure(100);
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
        
        double temp_VN;
        temp_VN = MultComputVN(0);        
        cout<< "#VN : " << temp_VN <<endl;
        return;
        
        for(i = 0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        tracedSigs.clear();
        for(int i =0 ; i < selected_traces.size(); i++)
        {
                tracedSigs.push_back(Ci->getFlipflop(selected_traces[i])->getOutput(0));
                tracedSigs[i]->setTraced(true,0);
        }
        
        Mymap = Mymap_Ori;
        std::sort(Mymap.begin(), Mymap.end(), lessRestoredMap);
        
        /*
        i = 0;
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                tracedSigs.push_back(Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0));
                tracedSigs[i]->setTraced(true,0);
                i++;
        }
        
        for(int i =0 ; i < islands.size(); i++)
        {
                tracedSigs.push_back(Ci->getFlipflop(islands[i])->getOutput(0));
                tracedSigs[i]->setTraced(true,0);
                }
        */
        /*
        while(tracedSigs.size() > trace_size)
        {
                C1 = new Confset();
                for(i = 0; i < tracedSigs.size(); i++)
                {
                        tracedSigs[i]->setTraced(false,0);
                        c1 = new Conf();
                        c1->tracedSigs.push_back(tracedSigs[i]);
                        initMultThread(1);
                        LoadInitDFFValue(0,0);
                        c1->TV = MultCalVN(0);
                        //c1->TV = MultComputVN();
                        c1->TVNC = c1->TV;
                        C1->confs.push_back(c1);
                        tracedSigs[i]->setTraced(true,0);
                }
                
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                cout<<"current trace size "<<tracedSigs.size()
                    <<" VN "<< C1->confs[0]->TV << endl;
                      
                it = find(tracedSigs.begin(), tracedSigs.end(), C1->confs[0]->tracedSigs[0]);
                assert( it != tracedSigs.end() );
                
                (*it)->setTraced(false,0);
                tracedSigs.erase(it);
                
                C1->~Confset();
        }
        
        for(i = 0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                (*it)->setTraced(true,0);
                cout<<(*it)->getName()<<"\t";
        }
        cout<<endl;        
        */
        
        double temp_P;
        j = 0;
        for(it_vec = root_traces.begin(); it_vec != root_traces.end() && j <= HeuTry; it_vec++){
                
                j++; i = 0;
                selected_traces.clear();
                Mymap = Mymap_Ori;
                
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        if((*it_map)->DFF_id == *it_vec)
                        {
                                it_map1 = it_map;
                                break;
                        }
                
                while(i != trace_size)
                {
                        i++;
                        //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
                        selected_traces.push_back((*it_map1)->DFF_id);
                        for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        {
                                if(it_map != it_map1)
                                {
                                        for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                                        {
                                                //if the DFF can be
                                                //restored from both 0 and 1
                                                if((*it_map)->R1.find(*it_set) != (*it_map)->R1.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P0;
                                                
                                                it_set1 = (*it_map)->R0.find(*it_set);                                                                
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                                
                                        }
                                        
                                        for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                                        {
                                                if((*it_map)->R0.find(*it_set) != (*it_map)->R0.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P1;
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                
                                                it_set1 = (*it_map)->R0.find(*it_set);
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                        }
                                }
                        }
                        
                        Mymap.erase(it_map1);
                        
                        weight = 0.0;
                        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                        {
                                temp_weight = (*it_map)->R0.size() * (*it_map)->P0 + 
                                        (*it_map)->R1.size() * (*it_map)->P1;
                        
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                        }
                
                        if(weight == 0.0)
                                break;
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
                
                tracedSigs.clear();
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                        tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
                }
                
                //double temp_VN = computVN();
                //double temp_VN = exhaustiveComputVN();
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double temp_VN = MultCalVN(0);
                
                if(temp_VN > cur_VN)
                {
                        cur_VN = temp_VN;
                        swap(final_traces,selected_traces);
                }
        }
        
        finish2 = clock();
        
        report<<"total runtime for DFF Simulation is: "<<( (finish1 - start1)/CLOCKS_PER_SEC )<<endl;
        report<<"total runtime for Heuristic Selection is: "<<( (finish2 - start2)/CLOCKS_PER_SEC )<<endl;
        report<<final_traces.size()<<endl;
        report<<"seleted signals are...."<<endl;
        
        cout<<"seleted signals are...."<<endl;
        for(it_vec = final_traces.begin(); it_vec != final_traces.end(); it_vec++)
        {
                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        }
        cout<<endl;
        report<<endl;
        
        cout<<"Visibility is "<<cur_VN<<endl;
        report<<cur_VN<<endl;
        
}

double Simulate::Check_Traces(const int trace_size)
{
        int cur_size = 0;
        string name;
        clearTraced();
        
        cout<<"Begin inputing traced flipflops...."<<endl;
        while(cur_size < trace_size)
        {
                std::getline(cin,name);
                for(int i=0; i<Ci->flipflopSize(); ++i)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == name)
                        {
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                                addTraced(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                cout<<"Another one..."<<endl;
                cur_size++;
        }
        cout<<"Inputing done!"<<endl;
        //double visibility = computVN();
        //double visibility = exhaustiveComputVN();
        initSimulate();
        SimInitDFFValue();

        double total_VN = 0.0;
        int seed_num = 3;
        for(int i = 0; i < seed_num; i++)
        {
                initMultThread(1);
                LoadInitDFFValue(50 + seed_num * 150, 0);
                total_VN += MultCalVN(0);
        }
        
        return total_VN / 3;
}

double Simulate::Check_Traces(const int trace_size, string &filename)
{
        int cur_size = 0;
        /*
        string name;
        clearTraced();
        cout<<"Begin inputing traced flipflops...."<<endl;
        while(cur_size < trace_size)
        {
        std::getline(cin,name);
        for(int i=0; i<Ci->flipflopSize(); ++i)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == name)
                        {
                               Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                                addTraced(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                cout<<"Another one..."<<endl;
                cur_size++;
        }
        
        cout<<"Inputing done!"<<endl;
        */
        
        if(!filename.empty())
        {
                string key ("bench");
                size_t found;

                found=filename.rfind(key);
                if (found!=string::npos)
                        filename.replace(found,key.length(),"report_greedy32");
                        //filename.replace (found,key.length(),"report_heu");
                        //filename.replace(found,key.length(),"report_prune");
                        //filename.replace (found,key.length(),"bench.32.traces");
                
                cout<<"filename is "<<filename<<endl;
        }
        
        ifstream in(filename.c_str());
        const int MAX_LINE_LENGTH = 65536;
        char line_buffer[MAX_LINE_LENGTH];
 
        while(1)
        {
                in.getline(line_buffer, MAX_LINE_LENGTH);
                char* p = strtok(line_buffer, "\t\n");
                if(!strcmp(p, "32"))
                        break;
        }
        in.getline(line_buffer, MAX_LINE_LENGTH);
        in.getline(line_buffer, MAX_LINE_LENGTH);
        
        char* s = strtok(line_buffer, "\t\n");
        vector<int> traced_dff_ids;
        
        while(s != NULL)
        {
                cout<<s<<endl;
                int flag = 0;
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        if(!strcmp(Ci->getFlipflop(i)->getOutput(0)->getName().c_str(),s))
                        {
                                flag = 1;
                                traced_dff_ids.push_back(i);
                                break;
                        }
                
                assert(flag == 1);
                s = strtok(NULL, "\t\n");
        }
        
        cout<<traced_dff_ids.size()<<endl;
        assert(traced_dff_ids.size() == 32);
        in.close();
        
        initSimulate();
        SimInitDFFValue();
        
        double total_vis = 0;
        const int seed_num = 3;
        const int trace_type = 3;
        pthread_t PTs[trace_type * seed_num];
        
        initMultithread_GREEDY(trace_type * seed_num);
        initMultThread(trace_type * seed_num);
        
        for(int j = 0; j < trace_type; j++)
        {
                for(int i = 0; i < seed_num; i++)
                {
                        if(j == 0)
                                for(int k = 0; k < 8; k++)
                                        Ci->getFlipflop(traced_dff_ids[k])->getOutput(0)->setTraced(true, j * trace_type + i);
                        else if(j == 1)
                                for(int k = 0; k < 16; k++)
                                        Ci->getFlipflop(traced_dff_ids[k])->getOutput(0)->setTraced(true, j * trace_type + i);
                        else
                                for(int k = 0; k < 32; k++)
                                        Ci->getFlipflop(traced_dff_ids[k])->getOutput(0)->setTraced(true, j * trace_type + i);
                        
                        myWorkarg* mwa= new myWorkarg;
                        mwa->Tid = j * trace_type + i;//should add pos later
                        mwa->Sim = this;
                        LoadInitDFFValue(50 + seed_num * 150,j * trace_type + i);
                        pthread_create(&PTs[j * trace_type + i], NULL, work, (void*)mwa);
                }
        }
        
        double Tvis[trace_type];
        memset(Tvis, 0.0, sizeof(double) * trace_type);

        for(int i = 0; i < trace_type * seed_num; i++)
        {
                myRetarg* mra = new myRetarg;
                pthread_join(PTs[i], (void**) &mra);
                
                Tvis[i/seed_num] += mra->VN;
                delete mra;
        }
        
        for(int i = 0; i < trace_type; i++)
        {
                if(i == 0)
                        cout<<"Total Vis for 8 is "<<Tvis[i]/seed_num <<endl;
                else if(i == 1)
                        cout<<"Total Vis for 16 is "<<Tvis[i]/seed_num <<endl;
                else
                        cout<<"Total Vis for 32 is "<<Tvis[i]/seed_num <<endl;
        }
        
        return 0.0;
}

void Simulate::findVicinityFlipflop(int DFF_id, vector<resVal> &R_seq_P, set<int> &R_seq, int dir){
        
        int k; queue<int> myQueue;//only contains gate ids
        
        for(k = 0; k<Ci->flipflopSize(); ++k)
                Ci->getFlipflop(k)->resetNumbering();
                        
        for(k = 0; k<Ci->gateSize(); ++k) 
        {
                Ci->getGate(k)->traversed = 0;
                Ci->getGate(k)->resetNumbering();
        }
        
        //initializing the stack
        if(dir == 0)//fanout cone
        {
                if(Ci->getFlipflop(DFF_id)->getOutput(0)->preset == false){
                        for(k = 0; k < Ci->getFlipflop(DFF_id)->getOutput(0)->outputSize(); k++){
                                {
                                        if(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->signature() == FLIPFLOP)
                                        {
                                                // R_seq.insert(k);
                                                
                                                // resVal RV;
                                                // RV.DFF_id = k;
                                                // if(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->getOutput(0)->getVal() == One)
                                                //         RV.val = 1;
                                                // else
                                                //         RV.val = 0;
                                                
                                                // R_seq_P.push_back(RV);
                                        }
                                        else
                                        {
                                                if(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->getOutput(0)->isKnown() == false)
                                                        Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->numbering = 1;
                                                
                                                myQueue.push(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->gate_index);
                                                Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->traversed = 1;
                                        }
                                }
                        }
                }
        }
        else//fanin cone
        {
                if(Ci->getFlipflop(DFF_id)->getInput(1)->preset == false){
                        for(k = 0; k < Ci->getFlipflop(DFF_id)->getInput(1)->inputSize(); k++){
                                {
                                        if(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->signature() == FLIPFLOP)
                                        {
                                                
                                        }
                                        else
                                        {
                                                if(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->getOutput(0)->isKnown() == false)
                                                        Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->numbering = 1;
                                                
                                                myQueue.push(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->gate_index);
                                                Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->traversed = 1;
                                        }
                                }
                        }
                }
        }
        
        vector<int> vicinity_DFFs;
        
        //iterative numbering
        if(dir == 0)//fanout cone
        {
                while(!myQueue.empty())
                {
                        int cur_gate_id = myQueue.front();
                        
                        if(Ci->getGate(cur_gate_id)->traversed >= 2)
                        {
                                myQueue.pop();
                                continue;
                        }
                        
                        Ci->getGate(cur_gate_id)->traversed++;
                        
                        //cout << "current gate id is " << cur_gate_id << endl;
                        for(k = 0; k < Ci->getGate(cur_gate_id)->getOutput(0)->outputSize(); k++){
                                
                                int flag = 0;
                                if(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->signature() == FLIPFLOP)
                                {
                                        /*
                                        R_seq.insert(k);
                                        
                                        resVal RV;
                                        RV.cur_gate_id = k;
                                        if(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else if(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->getOutput(0)->getVal() == Zero)
                                                RV.val = 0;
                                        else
                                                flag = 1;
                                        
                                        R_seq_P.push_back(RV);
                                        */
                                        vicinity_DFFs.push_back(((FlipflopNode*)(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)))->FF_index);
                                }
                                else
                                {
                                        if(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->getOutput(0)->isKnown() == false)
                                                flag = 1;
                                        
                                        myQueue.push(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->gate_index);
                                }
                                
                                if(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->traversed == 0)
                                {
                                        if(flag == 1)
                                                Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->numbering = Ci->getGate(cur_gate_id)->numbering + 1;
                                        else
                                                Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->numbering = Ci->getGate(cur_gate_id)->numbering;
                                }
                                
                                if(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->traversed == 1)
                                {
                                        if(flag == 1)
                                                Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->numbering = 
                                                        min(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->numbering ,Ci->getGate(cur_gate_id)->numbering + 1);
                                        else
                                                Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->numbering = 
                                                        min(Ci->getGate(cur_gate_id)->getOutput(0)->getOutput(k)->numbering, Ci->getGate(cur_gate_id)->numbering);
                                }
                      
                        }
                        
                        myQueue.pop();
                }
        }
        else
        {
                while(!myQueue.empty())
                {
                        int cur_gate_id = myQueue.front();
                        
                        if(Ci->getGate(cur_gate_id)->traversed >= 2)
                        {
                                myQueue.pop();
                                continue;
                        }
                        
                        Ci->getGate(cur_gate_id)->traversed++;
                        
                        //cout<< "current gate id is " << cur_gate_id << endl;
                        for(k = 0; k < Ci->getGate(cur_gate_id)->inputSize(); k++){
                                
                                int flag = 0;
                                if(Ci->getGate(cur_gate_id)->getInput(k)->inputSize() != 0){
                                        
                                        //if(Ci->getGate(cur_gate_id)->getInput(k)->inputSize() != 1)
                                        //cout << "name is " << Ci->getGate(cur_gate_id)->getInput(k)->getName() << endl;
                                        
                                        //output node does not hold
                                        //assert(Ci->getGate(cur_gate_id)->getInput(k)->inputSize() == 1);
                                        if(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->signature() == FLIPFLOP)
                                        {
                                                assert(((FlipflopNode*)(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)))->FF_index < Ci->flipflopSize());
                                                vicinity_DFFs.push_back(((FlipflopNode*)(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)))->FF_index);
                                        }
                                        else
                                        {
                                                if(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->getOutput(0)->isKnown() == false)
                                                        flag = 1;
                                                
                                                myQueue.push(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->gate_index);
                                        }
                                        
                                        if(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->traversed == 0)
                                        {
                                                if(flag == 1)
                                                        Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->numbering = Ci->getGate(cur_gate_id)->numbering + 1;
                                                else
                                                        Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->numbering = Ci->getGate(cur_gate_id)->numbering;
                                        }
                                        
                                        if(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->traversed == 1)
                                        {
                                                if(flag == 1)
                                                        Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->numbering = 
                                                                min(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->numbering, Ci->getGate(cur_gate_id)->numbering + 1);
                                                else
                                                        Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->numbering = 
                                                                min(Ci->getGate(cur_gate_id)->getInput(k)->getInput(0)->numbering, Ci->getGate(cur_gate_id)->numbering);
                                        }
                                }
                        }
                        
                        myQueue.pop();
                }
        }
        
        int count = 0;
        //pick the flipflops based on scores
        for(k = 0; k < vicinity_DFFs.size(); k++){
                if(Ci->getFlipflop(vicinity_DFFs[k])->numbering <= 3){
                        
                        R_seq.insert(vicinity_DFFs[k]);
                        
                        resVal RV;
                        RV.DFF_id = vicinity_DFFs[k];
                        RV.val = 2;
                        R_seq_P.push_back(RV);
                        
                        count++;
                }
        }
        
        //cout<<"add " << count << " to the current set." << endl;
        //cin.get();
}

pair<double,double> Simulate::huerSelectBiasedProcess(const int trace_size, vector<TresMap*> &Mymap , vector<int> &selected_traces, const char* filename, const double lampda){
        
        int i, j;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> MR;
        assert(selected_traces.size() == 0);
        
        cout<<"file name is "<<filename<<endl;        
        ofstream report(filename);
        report<< Ci->flipflopSize() <<endl;
        
        struct timeval start1, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                MR.clear();
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        //cout << "DFF id is " << (*it_map)->DFF_id << endl;
                        for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                        {
                                //cout << "check " << *it_set << endl;
                                temp_weight += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        }
                        
                        //how to deal with criticality is still unknown
                        for(it_set = (*it_map)->R0_com.begin(); it_set != (*it_map)->R0_com.end(); it_set++){
                                //cout << "check1 " << *it_set << endl;
                                temp_weight += lampda * probAdjustGate(Ci->getGate(*it_set), Ci->getGate(*it_set)->getOutput(0), (*it_map)->P0);
                        }

                        for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                //cout << "check2 " << *it_set << endl;
                                temp_weight += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        }
                        
                        //how to deal with criticality is still unknown
                        for(it_set = (*it_map)->R1_com.begin(); it_set != (*it_map)->R1_com.end(); it_set++){
                                //cout << "check3 " << *it_set << endl;
                                temp_weight += lampda * probAdjustGate(Ci->getGate(*it_set), Ci->getGate(*it_set)->getOutput(0), (*it_map)->P1);
                        }
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }

                        TmapRate myMR;
                        myMR.weight = temp_weight;
                        myMR.it_map = it_map;                
                        MR.push_back(myMR);
                }
                
                if(weight == 0.0)
                        break;
                
                std::sort(MR.begin(), MR.end(), TrateMapSort);
                
                double largest_weight = MR[0].weight;
                const double topK = 0.05;
                for(j = 0; j < MR.size(); j++)
                {
                        if(MR[j].weight < topK * largest_weight)
                                break;
                        
                        MR[j].weight = 0.0;
                }
                
                assert(j != 0);
                
                if(selected_traces.size() == 0)
                        j = 100;
                
                if( selected_traces.size() > 0 && j > 50 )
                        j = 50;
                
                MR.resize(j);
                
                const int thread_num = j;
                pthread_t PTs[thread_num];
                
                //cout << "thread_num is " << thread_num << endl;
                for(j = 0; j < thread_num; j++)
                {
                        for(i=0; i < Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i < selected_traces.size(); ++i)
                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                        
                        //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                        Ci->getFlipflop((*(MR[j].it_map))->DFF_id)->getOutput(0)->setTraced(true,j);
                }
                
                int seed_num = 0;
                while(seed_num < 3)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                LoadInitDFFValue(17 + seed_num * 200, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                
                                MR[mra->Tid].weight += mra->VN;
                                delete mra;
                        }
                        
                        seed_num++;
                }
                
                std::sort(MR.begin(), MR.end(), TrateMapSort);
                
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop((*(MR[0].it_map))->DFF_id)->getOutput(0)->getName() << endl;
                
                cout<<"VN is "<<MR[0].weight / 3 <<endl;
                selected_traces.push_back((*(MR[0].it_map))->DFF_id);
               
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                
                double cur_VN = MultCalVNWOLOCK(0);
                
                double restime = 0.0;
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                        Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                for(int j=0; j<Ci->gateSize(); ++j)
                {
                        restime = Ci->getGate(j)->getOutput(0)->isMultKnown(0);
                        Ci->getGate(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                it_map1 = MR[0].it_map;
                Mymap.erase(it_map1);
                
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, cur_VN);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish3, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                }
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        //double temp = MultCalVNWOLOCK(0);
        //return make_pair(temp, 0.0);
        //return MultCalVNWOLOCK(0);
        
        return reportSRR_GRR();
}

pair<double, double> Simulate::biasedSelect(const int trace_size, const char* filename, const double lampda){
        
        int i, j, k, flag;
        double weight, temp_weight, cur_VN;
        vector<TresMap*> Mymap;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        map< string, TresMap* > RSmap;

        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        //assignRandomWeight(0.2 * Ci->flipflopSize());
        
        struct timeval start1, finish1, finish2, finish3;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        initSimulate();
        cout << "sim init value starts" << endl;
        //SimInitDFFValue(filename);
        LoadDFFMap(filename);//make sure the weight file is read in. There
                             //are two LoadDFFMap functions
        cout << "sim init value ends" << endl;
        
        gettimeofday(&start1, NULL);
        //finish collecting resMap
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                flag = 0;
                TresMap* MyresMap = new TresMap;
                clearTraced();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                addTraced(Ci->getFlipflop(i)->getOutput(0));
                
                assert(tracedSigs.size() == 1);
                
                MyresMap->DFF_id = i;
                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->getP0();
                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->getP1();
                
                if(MyresMap->P0 == 0.0 && MyresMap->P1 == 0.0)
                {
                        cout<<"no Way!"<<endl;
                        cout<<"the signal name is "<<Ci->getFlipflop(i)->getOutput(0)->getName()<<endl;
                }
                //initSimulateGolden();
                initSimulateHybrid();
                PreSimHybrid1Trace();
                //sim_event(true);
                //sim_event(false);
                
                for(k = 0; k<Ci->flipflopSize(); ++k)
                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                simHybrid1Trace(true);

                for(k = 0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
                        {
                                if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R1_seq.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R1_seq_P.push_back(RV);
                                }
                        }
                
                for(k = 0; k<Ci->gateSize(); ++k){        
                        if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                if(Ci->getGate(k)->IsCritical == true)
                                {
                                        flag = 1;
                                        MyresMap->R1_com.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getGate(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R1_com_P.push_back(RV);        
                                }
                        }
                }
                
                findVicinityFlipflop(i, MyresMap->R1_seq_P, MyresMap->R1_seq, 0);
                findVicinityFlipflop(i, MyresMap->R1_seq_P, MyresMap->R1_seq, 1);
                
                //cout<<"# of DFFs stored when "<< Ci->getFlipflop(i)->getOutput(0)->getName() << " has value 1 is "
                //<< count_res1 << endl;
                
                //initSimulateGolden();
                initSimulateHybrid();
                PreSimHybrid1Trace();
                //sim_event(true);
                //sim_event(false);
                
                for(k = 0; k<Ci->flipflopSize(); ++k)
                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;

                simHybrid1Trace(false);
                
                int count_res0 = 0;
                for(k = 0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R0_seq.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R0_seq_P.push_back(RV);
                                        count_res0++;
                                }
                
                //cout<<"# of DFFs stored when "<< Ci->getFlipflop(i)->getOutput(0)->getName() << " has value 0 is "
                //<< count_res0 << endl;
                
                for(k = 0; k<Ci->gateSize(); ++k){        
                        if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                if(Ci->getGate(k)->IsCritical == true)
                                {
                                        flag = 1;
                                        MyresMap->R0_com.insert(k);
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getGate(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R0_com_P.push_back(RV);        
                                }
                        }
                }
                
                
                findVicinityFlipflop(i, MyresMap->R0_seq_P, MyresMap->R0_seq, 0);
                findVicinityFlipflop(i, MyresMap->R0_seq_P, MyresMap->R0_seq, 1);
                
                //cin.get();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                
                if(flag == 1)
                {
                        RSmap.insert(pair<string, TresMap*>(Ci->getFlipflop(i)->getOutput(0)->getName(), MyresMap) );
                        Mymap.push_back(MyresMap);
                }
                else
                        islands.push_back(i);
        }
        gettimeofday(&finish1, NULL);
        
        ofstream out("see"); 
        vector<TresMap*> Mymap_Ori(Mymap);
        set<int>::iterator it_RM;
        
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                out<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<"Name\t" << Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0)->getName()<<"\t"
                   <<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;                  
                out<<"When traced flipflop has value 0, restored DFF size is "<<(*it_map)->R0_seq.size()<<endl;
                for(it_RM = (*it_map)->R0_seq.begin(); it_RM != (*it_map)->R0_seq.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;
                
                out<<"When traced flipflop has value 1, restored DFF size is "<<(*it_map)->R1_seq.size()<<endl;
                for(it_RM = (*it_map)->R1_seq.begin(); it_RM != (*it_map)->R1_seq.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;                

                out<<"When traced flipflop has value 0, restored Critical gate size is "<<(*it_map)->R0_com.size()<<endl;
                for(it_RM = (*it_map)->R0_com.begin(); it_RM != (*it_map)->R0_com.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;
                
                out<<"When traced flipflop has value 1, restored Critical gate size is "<<(*it_map)->R1_com.size()<<endl;
                for(it_RM = (*it_map)->R1_com.begin(); it_RM != (*it_map)->R1_com.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;
                
                //cin.get();
        }        
        out.close();
        
        cout<< "total runtime spend on generating the reachibility list is "<< trace_size <<" is: "
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        gettimeofday(&start1, NULL);
        
        std::pair<double, double> SRR_GRR;
        SRR_GRR = huerSelectBiasedProcess(trace_size, Mymap, selected_traces, tmp.c_str(), lampda);
        const double init_SRR = SRR_GRR.first;
        cout << "Initial SRR is " << init_SRR << "\t";
        cout << "Initial GRR is " << SRR_GRR.second << endl;
        
        int try_time = 4;
        double lampda2;
        double lower_bound = 0.0;
        double upper_bound = 1.0;
        
        for(int i = 0; i < try_time; i++)
        {
                cout << "Optimization Round " << i << endl;
                lampda2 = 0.5 * (upper_bound + lower_bound);
                cout << "Lampda value is " << lampda2 << endl;
                
                Mymap = Mymap_Ori;
                selected_traces.clear();
                SRR_GRR = huerSelectBiasedProcess(trace_size, Mymap, selected_traces, tmp.c_str(), lampda2);
                
                if(SRR_GRR.first > 0.9 * init_SRR) //currently use 0.9 as the threshold
                        lower_bound = lampda2;
                else
                        upper_bound = lampda2;
                
                cout << "SRR is " << SRR_GRR.first << "\t"; 
                cout << "GRR is " << SRR_GRR.second << endl;
        }
        
        cout << "After " << try_time << " iterations, the final SRR and GRR are:" << endl;
        cout << "SRR is " << SRR_GRR.first << "\t"; 
        cout << "GRR is " << SRR_GRR.second << endl; 
        
        gettimeofday(&finish2, NULL);
        
        return SRR_GRR;
}
        
double Simulate::finalHeuSelectProcess(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces, const char* filename){
        /*
        int i, j;
        double weight_DFF, temp_weight_DFF, weight_Com, temp_weight_Com;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> MR_DFF;
        vector<TmapRate> MR_Com;
        assert(selected_traces.size() == 0);
        
        cout<<"file name is "<<filename<<endl;        
        ofstream report(filename);
        report<< Ci->flipflopSize() <<endl;
        
        struct timeval start1, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);
        
        for(int j=0; j<Ci->gateSize(); ++j)
                Ci->getGate(j)->weight = 0.0;
        
        while(selected_traces.size() < trace_size)
        {
                MR.clear();
                weight_DFF = 0.0;
                weight_Com = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight_DFF =0.0;
                        temp_weight_Com =0.0;
                        
                        for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                                temp_weight_DFF += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        //how to deal with criticality is still unknown
                        for(it_set = (*it_map)->R0_com.begin(); it_set != (*it_map)->R0_com.end(); it_set++)
                                temp_weight_DFF += lampda * probAdjust(Ci->getGate(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++)
                                temp_weight_DFF += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        //how to deal with criticality is still unknown
                        for(it_set = (*it_map)->R1_com.begin(); it_set != (*it_map)->R1_com.end(); it_set++)
                                temp_weight_DFF += lampda * probAdjust(Ci->getGate(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        if(temp_weight_DFF > weight_DFF)
                        {
                                it_map1 = it_map;
                                weight_DFF = temp_weight_DFF;
                        }
                        
                        TmapRate myMR;
                        myMR.weight = temp_weight_DFF;
                        myMR.it_map = it_map;                
                        MR.push_back(myMR);
                }
                
                if(weight_DFF == 0.0)
                        break;
                
                std::sort(MR.begin(), MR.end(), TrateMapSort);
                
                double largest_weight = MR[0].weight;
                const double topK = 0.05;
                for(j = 0; j < MR.size(); j++)
                {
                        if(MR[j].weight < topK * largest_weight)
                                break;
                        
                        MR[j].weight = 0.0;
                }
                
                assert(j != 0);
                
                if(selected_traces.size() == 0)
                        j = 100;
                
                if( selected_traces.size() > 0 && j > 50 )
                        j = 50;
                
                MR.resize(j);
                
                const int thread_num = j;
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        for(i=0; i < Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i < selected_traces.size(); ++i)
                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                        Ci->getFlipflop((*(MR[j].it_map))->DFF_id)->getOutput(0)->setTraced(true,j);
                }
                
                int seed_num = 0;
                while(seed_num < 2)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                LoadInitDFFValue(50 + seed_num * 150, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                
                                MR[mra->Tid].weight += mra->VN;
                                delete mra;
                        }
                        
                        seed_num++;
                }
                
                std::sort(MR.begin(), MR.end(), TrateMapSort);
                
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop((*(MR[0].it_map))->DFF_id)->getOutput(0)->getName() << endl;
                
                cout<<"VN is "<<MR[0].weight / 2 <<endl;
                selected_traces.push_back((*(MR[0].it_map))->DFF_id);
               
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                
                double cur_VN = MultCalVNWOLOCK(0);
                
                double restime = 0.0;
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                        Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                for(int j=0; j<Ci->gateSize(); ++j)
                {
                        restime = Ci->getGate(j)->getOutput(0)->isMultKnown(0);
                        Ci->getGate(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                
                

                it_map1 = MR[0].it_map;
                Mymap.erase(it_map1);
                
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, cur_VN);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish3, NULL);

                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                }
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
        */
}

void Simulate::finalHeuSelect(const int trace_size, const char* filename, const double lampda){
        
        int i, j, k, flag;
        double weight, temp_weight, cur_VN;
        vector<TresMap*> Mymap;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        map< string, TresMap* > RSmap;

        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        i = 0;
        while(tmp.c_str()[i] != 'b')
                i++;
        tmp.erase(tmp.begin()+i,tmp.end());
        tmp += "report_final_heu";
        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        assignRandomWeight(0.2 * Ci->flipflopSize());
        
        clock_t start1, finish1, start2, finish2;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        initSimulate();
        SimInitDFFValue();
        start1 = clock();
        //finish collecting resMap
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                flag = 0;
                TresMap* MyresMap = new TresMap;
                clearTraced();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                addTraced(Ci->getFlipflop(i)->getOutput(0));
                
                assert(tracedSigs.size() == 1);
                
                MyresMap->DFF_id = i;
                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->getP0();
                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->getP1();
                
                if(MyresMap->P0 == 0.0 && MyresMap->P1 == 0.0)
                {
                        cout<<"no Way!"<<endl;
                        cout<<"the signal name is "<<Ci->getFlipflop(i)->getOutput(0)->getName()<<endl;
                }
                //initSimulateGolden();
                //initSimulateHybrid();
                //sim_event(true);
                //sim_event(false);
                
                initSimulateHybrid();
                PreSimHybrid1Trace();
                //for(j=0; j<Ci->signalSize(); ++j)
                //Ci->getSignal(j)->stored = 0;
        
                for(k = 0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                //actually for gate, this is not neccessary since that
                //high criticality gates get restored automatically is the
                //best case of what we want. 
                //for(k = 0; k<Ci->gateSize(); ++k){        
                //if(Ci->getGate(k)->getOutput(0)->isKnown())
                //Ci->->getGate(k)->getOutput(0)->preset = true;

                simHybrid1Trace(true);

                for(k = 0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R1_seq.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R1_seq_P.push_back(RV);
                                }
                
                for(k=0; k<Ci->gateSize(); ++k){        
                        if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                if(Ci->getGate(k)->IsCritical == true)
                                {
                                        flag = 1;
                                        MyresMap->R1_com.insert(k);
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getGate(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R1_com_P.push_back(RV);        
                                }
                        }
                }
                
                //cout<<"# of DFFs stored when "<< Ci->getFlipflop(i)->getOutput(0)->getName() << " has value 1 is "
                //<< count_res1 << endl;
                
                //initSimulateGolden();
                //initSimulateHybrid();
                //sim_event(true);
                //sim_event(false);

                initSimulateHybrid();
                PreSimHybrid1Trace();
                //for(j=0; j<Ci->signalSize(); ++j)
                //Ci->getSignal(j)->stored = 0;

                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                simHybrid1Trace(false);
                
                int count_res0 = 0;
                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R0_seq.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R0_seq_P.push_back(RV);
                                        count_res0++;
                                }
                
                for(k=0; k<Ci->gateSize(); ++k){        
                        //any combinational gates that can be restored
                        if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                flag = 1;
                                MyresMap->R0_com.insert(k);
                                resVal RV;
                                RV.DFF_id = k;
                                if(Ci->getGate(k)->getOutput(0)->getVal() == One)
                                        RV.val = 1;
                                else
                                        RV.val = 0;
                                
                                MyresMap->R0_com_P.push_back(RV);        
                        }
                }
                
                //cin.get();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                
                if(flag == 1)
                {
                        RSmap.insert(pair<string, TresMap*>(Ci->getFlipflop(i)->getOutput(0)->getName(), MyresMap) );
                        Mymap.push_back(MyresMap);
                }
                else
                        islands.push_back(i);
        }
        finish1 = clock();
        
        
        vector<TresMap*> Mymap_Ori(Mymap);
        set<int>::iterator it_RM;
        
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                cout<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<"Name\t" << Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0)->getName()<<"\t"
                   <<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                   
                cout<<"When traced flipflop has value 0, restored DFF size is "<<(*it_map)->R0_seq.size()<<endl;
                for(it_RM = (*it_map)->R0_seq.begin(); it_RM != (*it_map)->R0_seq.end(); it_RM++)
                        cout<<(*it_RM)<<"\t";
                cout<<endl;
                
                cout<<"When traced flipflop has value 1, restored DFF size is "<<(*it_map)->R1_seq.size()<<endl;
                for(it_RM = (*it_map)->R1_seq.begin(); it_RM != (*it_map)->R1_seq.end(); it_RM++)
                        cout<<(*it_RM)<<"\t";
                cout<<endl;                

                cout<<"When traced flipflop has value 0, restored Critical gate size is "<<(*it_map)->R0_com.size()<<endl;
                for(it_RM = (*it_map)->R0_com.begin(); it_RM != (*it_map)->R0_com.end(); it_RM++)
                        cout<<(*it_RM)<<"\t";
                cout<<endl;
                
                cout<<"When traced flipflop has value 1, restored Critical gate size is "<<(*it_map)->R1_com.size()<<endl;
                for(it_RM = (*it_map)->R1_com.begin(); it_RM != (*it_map)->R1_com.end(); it_RM++)
                        cout<<(*it_RM)<<"\t";
                cout<<endl;
                
                //cin.get();
        }        
        
        start2 = clock();
        cout<<"The time spend on generating the reachibility list is "<< ( (finish1 - start1)/CLOCKS_PER_SEC )<<endl;
        cout<<"Should be added later!"<<endl;
        
        //cur_VN = huerSelectBiasedProcess(trace_size, Mymap, selected_traces, tmp.c_str(), lampda);
        cout<<"Initial VN is "<<cur_VN<<endl;        
        
        vector<int> final_traces;
        vector<int> root_traces(selected_traces);
        
        finish2 = clock();
        double temp_VN = cur_VN;
        cout<< "#VN : " << temp_VN <<endl;
        
}

void Simulate::assignRandomWeight(const int crit_gate_num){
        
        int k, count = 0;
        double criticality;
        const long rand_max = 2e10;

        for(k=0; k<Ci->gateSize(); ++k){
                Ci->getGate(k)->IsCritical = false;
                Ci->getGate(k)->weight = 0.0;
        }
        
        while(count < crit_gate_num){
                
                k = rand() % Ci->gateSize();
                criticality = (double) (rand() % rand_max) / (double) rand_max;
                assert(fabs(criticality) < 1.0);
                
                Ci->getGate(k)->IsCritical = true;
                Ci->getGate(k)->weight = criticality;
                //Ci->getGate(k)->weight = 0.0;
                
                count++;
        }
        
}

